Primal Server exposes a WebSocket-based API for Nostr clients, inspired by and extending the NIP-01 protocol. While it reuses some NIP-01 verbs like REQ and CLOSE, it significantly extends the protocol with custom filters and cache endpoints designed for efficient content discovery and social features.
Connect to the WebSocket endpoint at:
ws://127.0.0.1:8801
For production environments, use:
wss://cache.primal.net/v1
All messages are JSON arrays sent over WebSocket connections.
---
REQ - Request/SubscribeUsed to request cached data or events and subscribe to updates.
Basic Format:
["REQ", <subscription_id>, <filters>]
Comparison to NIP-01:
- Similar: Uses the same REQ verb and subscription_id concept
- Different: Primal cache servers do NOT accept standard NIP-01 filters (ids, authors, kinds, etc.)
- Different: Instead, Primal uses a special cache field for accessing pre-computed data through named endpoints
#### Primal Cache Filter Format
IMPORTANT: Primal's cache server does NOT accept regular NIP-01 filters. All requests must use the cache field format:
{
"cache": ["<endpoint_name>", {<parameters>}]
}
Note: Standard NIP-01 filters like ids, authors, kinds, #e, #p, since, until, and limit are NOT supported by Primal's cache server. Each cache endpoint has its own specific parameters (documented below).
If you need to query events using standard NIP-01 filters, you should connect to regular Nostr relays (like wss://relay.primal.net) instead of the cache server
{
"cache": ["<endpoint_name>", {<parameters>}]
}
All cache endpoints are accessed via the cache filter field. Below is a comprehensive list:
#### Network & Statistics
net_stats - Network statistics (async)
["REQ", "sub_id", {"cache": ["net_stats"]}]
nostr_stats - Nostr network stats
["REQ", "sub_id", {"cache": ["nostr_stats"]}]
server_name - Get server name
["REQ", "sub_id", {"cache": ["server_name"]}]
#### Feed Endpoints
feed - User feed
["REQ", "sub_id", {
"cache": ["feed", {
"pubkey": "<pubkey>",
"notes": "follows|authored|bookmarks|user_media_thumbnails",
"include_replies": true|false,
"limit": 20,
"since": <timestamp>,
"until": <timestamp>,
"offset": 0,
"user_pubkey": "<optional_viewer_pubkey>"
}]
}]
Parameters:
- pubkey: Target user's public key (hex)
- notes: Feed type
- "follows": Posts from users this pubkey follows
- "authored": Posts created by this pubkey
- "replies": Only replies by this pubkey
- "bookmarks": Bookmarked posts
- "user_media_thumbnails": Posts with media
- include_replies: Include reply posts (default: false)
- limit: Max results (≤1000)
- since/until: Unix timestamp range
- offset: Pagination offset
- user_pubkey: Viewer's pubkey for personalization
Returns:
- Kind 1: Text notes
- Kind 6: Reposts
- Kind 9735: Zap receipts
- Kind 0: User metadata for all mentioned users
- Kind 10000100: EVENT_STATS (engagement metrics per event)
- Kind 10000107: REFERENCED_EVENT (full quoted/reposted events)
- Kind 10000108: USER_SCORES (user scoring data)
- Kind 10000113: RANGE (pagination metadata with event IDs)
- Kind 10000128: LINK_METADATA (URL preview data)
- Kind 10000129: ZAP_EVENT (detailed zap information)
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000141: EVENT_RELAYS (where events were seen)
- Kind 10000158: USER_PRIMAL_NAMES
- Kind 10000168: MEMBERSHIP_LEGEND_CUSTOMIZATION
- Kind 10000169: MEMBERSHIP_COHORTS
- Kind 10063: User relay lists
feed_2 - Extended feed endpoint
["REQ", "sub_id", {
"cache": ["feed_2", {
"pubkey": "<pubkey>",
"notes": "follows|authored",
"kinds": [1, 6],
"since": <timestamp>,
"until": <timestamp>,
"limit": 20,
"offset": 0,
"order": "asc|desc",
"user_pubkey": "<viewer_pubkey>"
}]
}]
Additional parameters:
- kinds: Filter by event kinds
- order: Sort order (asc/desc)
thread_view - Conversation thread
["REQ", "sub_id", {
"cache": ["thread_view", {
"event_id": "<event_id>",
"limit": 20,
"since": <timestamp>,
"until": <timestamp>,
"offset": 0,
"user_pubkey": "<viewer_pubkey>"
}]
}]
Returns the specified event along with its replies and parent posts.
Returns:
- Kind 1: The target event, parent posts, and reply posts
- Kind 0: User metadata for all participants in the thread
- Kind 10000100: EVENT_STATS for each event
- Kind 10000107: REFERENCED_EVENT (quoted posts)
- Kind 10000108: USER_SCORES
- Kind 10000119: MEDIA_METADATA
- Kind 10000129: ZAP_EVENT (zaps on thread events)
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000158: USER_PRIMAL_NAMES
#### User Profile & Social Graph
user_profile - User profile information
["REQ", "sub_id", {
"cache": ["user_profile", {
"pubkey": "<pubkey>",
"user_pubkey": "<viewer_pubkey>"
}]
}]
Returns:
- Kind 0: User metadata event
- Kind 10000105: USER_PROFILE with follower/note counts
- Kind 10000119: MEDIA_METADATA for profile images
- Kind 10000169: MEMBERSHIP_COHORTS (premium/legend status)
- Kind 10063: User relay list (NIP-65)
user_infos - Batch user information
["REQ", "sub_id", {
"cache": ["user_infos", {
"pubkeys": ["<pubkey1>", "<pubkey2>", ...]
}]
}]
Returns multiple event types for each user:
- Kind 0: User metadata
- Kind 10000108: USER_SCORES (follower-based scores)
- Kind 10000133: USER_FOLLOWER_COUNTS (actual follower counts)
- Kind 10000119: MEDIA_METADATA (profile image variants)
- Kind 10000158: USER_PRIMAL_NAMES (verified Primal usernames)
- Kind 10000169: MEMBERSHIP_COHORTS (premium status)
- Kind 10063: User relay list
contact_list - User's contact list
["REQ", "sub_id", {
"cache": ["contact_list", {
"pubkey": "<pubkey>",
"extended_response": true|false
}]
}]
is_user_following - Check if user follows another
["REQ", "sub_id", {
"cache": ["is_user_following", {
"pubkey": "<follower_pubkey>",
"user_pubkey": "<target_pubkey>"
}]
}]
user_followers - Get user followers
["REQ", "sub_id", {
"cache": ["user_followers", {
"pubkey": "<pubkey>",
"limit": 200
}]
}]
mutual_follows - Mutual followers between users
["REQ", "sub_id", {
"cache": ["mutual_follows", {
"pubkey": "<pubkey>",
"user_pubkey": "<viewer_pubkey>"
}]
}]
user_profile_followed_by - Who follows this user
["REQ", "sub_id", {
"cache": ["user_profile_followed_by", {
"pubkey": "<pubkey>"
}]
}]
#### Events & Actions
events - Get specific events
["REQ", "sub_id", {
"cache": ["events", {
"event_ids": ["<event_id1>", "<event_id2>", ...],
"extended_response": true|false,
"user_pubkey": "<viewer_pubkey>"
}]
}]
event_actions - Event interactions (likes, reposts, etc.)
["REQ", "sub_id", {
"cache": ["event_actions", {
"event_id": "<event_id>",
"kind": <action_kind>,
"limit": 100,
"offset": 0
}]
}]
Or for addressable events:
{
"cache": ["event_actions", {
"pubkey": "<pubkey>",
"identifier": "<d_tag_value>",
"kind": <action_kind>,
"limit": 100,
"offset": 0
}]
}
Action kind values:
- 7 - Likes/reactions
- 1 - Replies (text notes that reference the event)
- 6 - Reposts/quotes
- 9735 - Zap receipts
Returns:
- Events of the specified kind that reference the target event
- Kind 0: User metadata for all users who performed the action
- Additional metadata as needed
#### Zaps
zaps_feed - Zap feed
["REQ", "sub_id", {
"cache": ["zaps_feed", {
"pubkey": "<pubkey>",
"limit": 20,
"offset": 0
}]
}]
user_zaps - Zaps received by user
["REQ", "sub_id", {
"cache": ["user_zaps", {
"pubkey": "<pubkey>",
"limit": 20,
"offset": 0
}]
}]
user_zaps_by_satszapped - Zaps sorted by amount
["REQ", "sub_id", {
"cache": ["user_zaps_by_satszapped", {
"pubkey": "<pubkey>",
"limit": 20,
"offset": 0
}]
}]
user_zaps_sent - Zaps sent by user
["REQ", "sub_id", {
"cache": ["user_zaps_sent", {
"pubkey": "<pubkey>",
"limit": 20,
"offset": 0
}]
}]
event_zaps_by_satszapped - Zaps on specific event
["REQ", "sub_id", {
"cache": ["event_zaps_by_satszapped", {
"event_id": "<event_id>",
"limit": 20,
"offset": 0,
"user_pubkey": "<viewer_pubkey>"
}]
}]
Or for addressable events:
{
"cache": ["event_zaps_by_satszapped", {
"pubkey": "<pubkey>",
"identifier": "<d_tag_value>",
"limit": 20,
"offset": 0,
"user_pubkey": "<viewer_pubkey>"
}]
}
invoices_to_zap_receipts - Convert invoices to zap receipts
["REQ", "sub_id", {
"cache": ["invoices_to_zap_receipts", {
"invoices": ["<invoice1>", "<invoice2>", ...]
}]
}]
#### Direct Messages
get_directmsg_contacts - Get DM contacts
["REQ", "sub_id", {
"cache": ["get_directmsg_contacts", {
"receiver_pubkey": "<pubkey>",
"user_pubkey": "<viewer_pubkey>"
}]
}]
get_directmsgs - Get direct messages
["REQ", "sub_id", {
"cache": ["get_directmsgs", {
"receiver": "<receiver_pubkey>",
"sender": "<sender_pubkey>",
"user_pubkey": "<viewer_pubkey>",
"limit": 20,
"since": <timestamp>,
"until": <timestamp>
}]
}]
directmsg_count - DM count (async)
["REQ", "sub_id", {
"cache": ["directmsg_count", {
"receiver_pubkey": "<pubkey>"
}]
}]
directmsg_count_2 - Extended DM count (async)
["REQ", "sub_id", {
"cache": ["directmsg_count_2", {
"receiver_pubkey": "<pubkey>"
}]
}]
reset_directmsg_count - Reset DM counter
["REQ", "sub_id", {
"cache": ["reset_directmsg_count", {
"receiver_pubkey": "<pubkey>",
"sender_pubkey": "<sender_pubkey>"
}]
}]
reset_directmsg_counts - Reset all DM counters
["REQ", "sub_id", {
"cache": ["reset_directmsg_counts", {
"receiver_pubkey": "<pubkey>"
}]
}]
#### Content Moderation
mutelist - Get mute list
["REQ", "sub_id", {
"cache": ["mutelist", {
"pubkey": "<pubkey>"
}]
}]
mutelists - Get multiple mute lists
["REQ", "sub_id", {
"cache": ["mutelists", {
"pubkeys": ["<pubkey1>", "<pubkey2>", ...]
}]
}]
allowlist - Get allow list
["REQ", "sub_id", {
"cache": ["allowlist", {
"pubkey": "<pubkey>"
}]
}]
is_hidden_by_content_moderation - Check if content is hidden
["REQ", "sub_id", {
"cache": ["is_hidden_by_content_moderation", {
"pubkey": "<viewer_pubkey>",
"event_id": "<event_id>"
}]
}]
#### Explore & Discovery
explore_zaps - Trending zaps
["REQ", "sub_id", {
"cache": ["explore_zaps", {
"limit": 20,
"user_pubkey": "<viewer_pubkey>"
}]
}]
explore_people - Discover users
["REQ", "sub_id", {
"cache": ["explore_people", {
"limit": 20,
"user_pubkey": "<viewer_pubkey>"
}]
}]
explore_media - Trending media
["REQ", "sub_id", {
"cache": ["explore_media", {
"limit": 20,
"user_pubkey": "<viewer_pubkey>"
}]
}]
explore_topics - Trending topics
["REQ", "sub_id", {
"cache": ["explore_topics", {
"limit": 20,
"user_pubkey": "<viewer_pubkey>"
}]
}]
scored - Get scored/trending content
["REQ", "sub_id", {
"cache": ["scored", {
"selector": "trending_24h|trending_12h|trending_4h|mostzapped_24h|...",
"user_pubkey": "<viewer_pubkey>"
}]
}]
Supported selectors:
- trending_24h, trending_12h, trending_4h, trending_1h - Trending by engagement
- mostzapped_24h, mostzapped_12h, mostzapped_4h, mostzapped_1h - Most zapped
- gm_trending_24h, gm_trending_12h, gm_trending_4h, gm_trending_1h - GM posts
- classic_trending_24h, classic_trending_12h, classic_trending_4h, classic_trending_1h - Classic algorithm
Returns:
- Kind 1: Posts matching the scoring criteria
- Kind 0: User metadata
- Kind 10000100: EVENT_STATS (detailed engagement metrics)
- Kind 10000107: REFERENCED_EVENT
- Kind 10000119: MEDIA_METADATA
- Kind 10000128: LINK_METADATA
- Additional metadata kinds
scored_users - Trending users
["REQ", "sub_id", {
"cache": ["scored_users", {
"limit": 20,
"since": <timestamp>,
"user_pubkey": "<viewer_pubkey>"
}]
}]
scored_users_24h - Trending users (24h)
["REQ", "sub_id", {
"cache": ["scored_users_24h", {
"user_pubkey": "<viewer_pubkey>"
}]
}]
explore_global_trending_24h - Global trending (24h)
["REQ", "sub_id", {
"cache": ["explore_global_trending_24h", {
"user_pubkey": "<viewer_pubkey>"
}]
}]
Returns:
- Kind 1: Trending text notes
- Kind 0: User metadata for post authors
- Kind 9735: Zap receipts on trending posts
- Kind 10000100: EVENT_STATS with engagement metrics
- Kind 10000107: REFERENCED_EVENT (quoted posts)
- Kind 10000119: MEDIA_METADATA (image/video thumbnails)
- Kind 10000128: LINK_METADATA (URL previews)
- Kind 10000129: ZAP_EVENT (zap details)
- Additional metadata kinds
explore_global_mostzapped_4h - Most zapped globally (4h)
["REQ", "sub_id", {
"cache": ["explore_global_mostzapped_4h", {
"user_pubkey": "<viewer_pubkey>"
}]
}]
explore - General explore endpoint
["REQ", "sub_id", {
"cache": ["explore", {
"timeframe": "latest|popular|trending|mostzapped",
"scope": "global|network|tribe|follows",
"user_pubkey": "<viewer_pubkey>",
"limit": 20,
"since": <timestamp>,
"until": <timestamp>
}]
}]
explore_legend_counts - Network statistics for user
["REQ", "sub_id", {
"cache": ["explore_legend_counts", {
"pubkey": "<pubkey>"
}]
}]
#### Search
search - Search events
["REQ", "sub_id", {
"cache": ["search", {
"query": "<search_query>",
"kind": <kind_filter>,
"limit": 20,
"since": <timestamp>,
"until": <timestamp>,
"offset": 0,
"user_pubkey": "<viewer_pubkey>"
}]
}]
Returns:
- Matching events (typically kind 1 text notes)
- Kind 0: User metadata for post authors
- Kind 10000100: EVENT_STATS
- Additional metadata kinds as needed
advanced_search - Advanced search with filters
["REQ", "sub_id", {
"cache": ["advanced_search", {
"query": "<search_query>",
"user_pubkey": "<viewer_pubkey>",
"limit": 20
}]
}]
user_search - Search users
["REQ", "sub_id", {
"cache": ["user_search", {
"query": "<search_query>",
"limit": 20,
"pubkey": "<optional_searcher_pubkey>"
}]
}]
Returns:
- Kind 0 (user metadata for matching users)
- Kind 10000108 (USER_SCORES)
- Kind 10000133 (USER_FOLLOWER_COUNTS)
- Kind 10000158 (USER_PRIMAL_NAMES)
#### Long-form Content (Articles)
long_form_content_feed - Article feed
["REQ", "sub_id", {
"cache": ["long_form_content_feed", {
"pubkey": "<pubkey>",
"limit": 20,
"since": <timestamp>,
"until": <timestamp>,
"offset": 0,
"user_pubkey": "<viewer_pubkey>"
}]
}]
long_form_content_thread_view - Article with comments
["REQ", "sub_id", {
"cache": ["long_form_content_thread_view", {
"event_id": "<article_event_id>",
"limit": 20,
"user_pubkey": "<viewer_pubkey>"
}]
}]
get_recommended_reads - Recommended articles
["REQ", "sub_id", {
"cache": ["get_recommended_reads", {
"pubkey": "<pubkey>",
"limit": 20
}]
}]
get_reads_topics - Article topics
["REQ", "sub_id", {
"cache": ["get_reads_topics"]}]
}]
get_featured_authors - Featured article authors
["REQ", "sub_id", {
"cache": ["get_featured_authors"]}]
}]
articles_stats - Article statistics
["REQ", "sub_id", {
"cache": ["articles_stats", {
"pubkey": "<pubkey>"
}]
}]
drafts - Article drafts
["REQ", "sub_id", {
"cache": ["drafts", {
"pubkey": "<pubkey>"
}]
}]
top_article - Top article
["REQ", "sub_id", {
"cache": ["top_article", {
"pubkey": "<pubkey>"
}]
}]
#### Bookmarks & Highlights
get_bookmarks - Get bookmarks
["REQ", "sub_id", {
"cache": ["get_bookmarks", {
"pubkey": "<pubkey>"
}]
}]
get_highlights - Get highlights
["REQ", "sub_id", {
"cache": ["get_highlights", {
"pubkey": "<pubkey>"
}]
}]
#### Relays
get_user_relays - User relay list
["REQ", "sub_id", {
"cache": ["get_user_relays", {
"pubkey": "<pubkey>"
}]
}]
get_user_relays_2 - Extended relay list
["REQ", "sub_id", {
"cache": ["get_user_relays_2", {
"pubkey": "<pubkey>"
}]
}]
relays - Popular relays
["REQ", "sub_id", {
"cache": ["relays", {
"limit": 20
}]
}]
get_default_relays - Default relay recommendations
["REQ", "sub_id", {
"cache": ["get_default_relays"]}]
}]
#### Recommendations
get_recommended_users - Recommended users to follow
["REQ", "sub_id", {
"cache": ["get_recommended_users"]}]
}]
get_suggested_users - Suggested user accounts
["REQ", "sub_id", {
"cache": ["get_suggested_users"]}]
}]
#### Feeds & Directives
feed_directive - Custom feed directive
["REQ", "sub_id", {
"cache": ["feed_directive", {
"directive": "<directive_config>"
}]
}]
feed_directive_2 - Extended feed directive
["REQ", "sub_id", {
"cache": ["feed_directive_2", {
"directive": "<directive_config>"
}]
}]
mega_feed_directive - Mega feed endpoint
["REQ", "sub_id", {
"cache": ["mega_feed_directive", {
"spec": "<feed_specification>"
}]
}]
advanced_feed - Advanced feed
["REQ", "sub_id", {
"cache": ["advanced_feed", {
"specification": "<feed_spec>"
}]
}]
get_advanced_feeds - Available advanced feeds
["REQ", "sub_id", {
"cache": ["get_advanced_feeds"]}]
}]
get_home_feeds - Home feed configurations
["REQ", "sub_id", {
"cache": ["get_home_feeds"]}]
}]
get_reads_feeds - Article feed configurations
["REQ", "sub_id", {
"cache": ["get_reads_feeds"]}]
}]
enrich_feed_events - Enrich feed with metadata
["REQ", "sub_id", {
"cache": ["enrich_feed_events", {
"events": [<event_array>]
}]
}]
#### DVM (Data Vending Machines)
get_dvm_feeds - DVM feed list
["REQ", "sub_id", {
"cache": ["get_dvm_feeds"]}]
}]
dvm_feed_info - DVM feed details
["REQ", "sub_id", {
"cache": ["dvm_feed_info", {
"feed_id": "<feed_id>"
}]
}]
get_featured_dvm_feeds - Featured DVM feeds
["REQ", "sub_id", {
"cache": ["get_featured_dvm_feeds"]}]
}]
#### Settings & Configuration
set_app_settings - Set user app settings
["REQ", "sub_id", {
"cache": ["set_app_settings", {
"settings_event": <signed_event>
}]
}]
get_app_settings - Get app settings
["REQ", "sub_id", {
"cache": ["get_app_settings", {
"event_from_user": <signed_event>
}]
}]
get_app_settings_2 - Extended app settings
["REQ", "sub_id", {
"cache": ["get_app_settings_2", {
"event_from_user": <signed_event>
}]
}]
get_default_app_settings - Default app settings
["REQ", "sub_id", {
"cache": ["get_default_app_settings", {
"client": "Primal-Web App"
}]
}]
set_app_subsettings - Set app subsettings
["REQ", "sub_id", {
"cache": ["set_app_subsettings", {
"event_from_user": <signed_event>
}]
}]
get_app_subsettings - Get app subsettings
["REQ", "sub_id", {
"cache": ["get_app_subsettings", {
"event_from_user": <signed_event>
}]
}]
get_default_app_subsettings - Default subsettings
["REQ", "sub_id", {
"cache": ["get_default_app_subsettings", {
"subkey": "user-home-feeds|user-reads-feeds"
}]
}]
client_config - Client configuration
["REQ", "sub_id", {
"cache": ["client_config"]}]
}]
get_app_releases - App release information
["REQ", "sub_id", {
"cache": ["get_app_releases"]}]
}]
#### Notifications
notifications - Get notifications (async)
["REQ", "sub_id", {
"cache": ["notifications", {
"pubkey": "<pubkey>"
}]
}]
notification_counts - Notification counts (async)
["REQ", "sub_id", {
"cache": ["notification_counts", {
"pubkey": "<pubkey>"
}]
}]
notification_counts_2 - Extended notification counts (async)
["REQ", "sub_id", {
"cache": ["notification_counts_2", {
"pubkey": "<pubkey>"
}]
}]
get_notifications - Get notifications with filters
["REQ", "sub_id", {
"cache": ["get_notifications", {
"pubkey": "<pubkey>",
"limit": 1000,
"since": <timestamp>,
"until": <timestamp>,
"offset": 0,
"user_pubkey": "<viewer_pubkey>",
"type": "<notification_type>",
"type_group": "<type_group>"
}]
}]
set_notifications_seen - Mark notifications as seen
["REQ", "sub_id", {
"cache": ["set_notifications_seen", {
"event_from_user": <signed_event>
}]
}]
get_notifications_seen - Get seen notification timestamp
["REQ", "sub_id", {
"cache": ["get_notifications_seen", {
"event_from_user": <signed_event>
}]
}]
#### Push Notifications
update_push_notification_token - Update push token
["REQ", "sub_id", {
"cache": ["update_push_notification_token", {
"event_from_user": <signed_event>
}]
}]
update_push_notification_token_for_nip46 - Update push token for NIP-46
["REQ", "sub_id", {
"cache": ["update_push_notification_token_for_nip46", {
"event_from_user": <signed_event>
}]
}]
events_nip46 - NIP-46 events
["REQ", "sub_id", {
"cache": ["events_nip46", {
"pubkey": "<pubkey>"
}]
}]
#### Hashtags & Trending
trending_hashtags_4h - Trending hashtags (4h)
["REQ", "sub_id", {
"cache": ["trending_hashtags_4h"]}]
}]
trending_hashtags_7d - Trending hashtags (7d)
["REQ", "sub_id", {
"cache": ["trending_hashtags_7d"]}]
}]
trending_images - Trending images
["REQ", "sub_id", {
"cache": ["trending_images", {
"limit": 20
}]
}]
trending_images_4h - Trending images (4h)
["REQ", "sub_id", {
"cache": ["trending_images_4h"]}]
}]
#### Lists & Collections
parameterized_replaceable_list - Get parameterized replaceable list
["REQ", "sub_id", {
"cache": ["parameterized_replaceable_list", {
"pubkey": "<pubkey>",
"identifier": "<d_tag>",
"kind": <kind_number>
}]
}]
parametrized_replaceable_event - Get single parameterized event
["REQ", "sub_id", {
"cache": ["parametrized_replaceable_event", {
"pubkey": "<pubkey>",
"identifier": "<d_tag>",
"kind": <kind_number>
}]
}]
parametrized_replaceable_events - Get multiple parameterized events
["REQ", "sub_id", {
"cache": ["parametrized_replaceable_events", {
"pubkey": "<pubkey>",
"identifiers": ["<d_tag1>", "<d_tag2>", ...],
"kind": <kind_number>
}]
}]
replaceable_event - Get replaceable event
["REQ", "sub_id", {
"cache": ["replaceable_event", {
"pubkey": "<pubkey>",
"kind": <kind_number>
}]
}]
follow_lists - Get follow lists
["REQ", "sub_id", {
"cache": ["follow_lists", {
"pubkey": "<pubkey>"
}]
}]
follow_list - Get specific follow list
["REQ", "sub_id", {
"cache": ["follow_list", {
"pubkey": "<pubkey>",
"identifier": "<d_tag>"
}]
}]
#### Content Filtering
search_filterlist - Search filter list
["REQ", "sub_id", {
"cache": ["search_filterlist", {
"query": "<search_query>"
}]
}]
get_filterlist - Get filter list
["REQ", "sub_id", {
"cache": ["get_filterlist", {
"pubkey": "<pubkey>"
}]
}]
check_filterlist - Check if filtered
["REQ", "sub_id", {
"cache": ["check_filterlist", {
"target": "<pubkey_or_event_id>",
"target_type": "pubkey|event"
}]
}]
#### Reporting
report_user - Report user
["REQ", "sub_id", {
"cache": ["report_user", {
"event_from_user": <signed_event>
}]
}]
report_note - Report note
["REQ", "sub_id", {
"cache": ["report_note", {
"event_from_user": <signed_event>
}]
}]
#### Event Broadcasting
import_events - Import events
["REQ", "sub_id", {
"cache": ["import_events", {
"events": [<event_array>]
}]
}]
broadcast_reply - Broadcast reply
["REQ", "sub_id", {
"cache": ["broadcast_reply", {
"event_from_user": <signed_event>
}]
}]
broadcast_events - Broadcast multiple events
["REQ", "sub_id", {
"cache": ["broadcast_events", {
"events": [<event_array>]
}]
}]
#### Membership Features
membership_media_management_stats - Media storage stats
["REQ", "sub_id", {
"cache": ["membership_media_management_stats", {
"event_from_user": <signed_event>
}]
}]
membership_media_management_uploads - List uploads
["REQ", "sub_id", {
"cache": ["membership_media_management_uploads", {
"event_from_user": <signed_event>
}]
}]
membership_media_management_delete - Delete uploads
["REQ", "sub_id", {
"cache": ["membership_media_management_delete", {
"event_from_user": <signed_event>
}]
}]
membership_recovery_contact_lists - Recover contact lists
["REQ", "sub_id", {
"cache": ["membership_recovery_contact_lists", {
"event_from_user": <signed_event>
}]
}]
membership_recover_contact_list - Recover specific contact list
["REQ", "sub_id", {
"cache": ["membership_recover_contact_list", {
"event_from_user": <signed_event>
}]
}]
membership_content_stats - Content backup stats
["REQ", "sub_id", {
"cache": ["membership_content_stats", {
"event_from_user": <signed_event>
}]
}]
membership_content_backup - Backup content
["REQ", "sub_id", {
"cache": ["membership_content_backup", {
"event_from_user": <signed_event>
}]
}]
membership_content_rebroadcast_start - Start rebroadcast
["REQ", "sub_id", {
"cache": ["membership_content_rebroadcast_start", {
"event_from_user": <signed_event>
}]
}]
membership_content_rebroadcast_cancel - Cancel rebroadcast
["REQ", "sub_id", {
"cache": ["membership_content_rebroadcast_cancel", {
"event_from_user": <signed_event>
}]
}]
membership_content_rebroadcast_status - Rebroadcast status
["REQ", "sub_id", {
"cache": ["membership_content_rebroadcast_status", {
"event_from_user": <signed_event>
}]
}]
rebroadcasting_status - Get rebroadcast status (async)
["REQ", "sub_id", {
"cache": ["rebroadcasting_status", {
"pubkey": "<pubkey>"
}]
}]
membership_legends_leaderboard - Legends leaderboard
["REQ", "sub_id", {
"cache": ["membership_legends_leaderboard"]}]
}]
membership_premium_leaderboard - Premium leaderboard
["REQ", "sub_id", {
"cache": ["membership_premium_leaderboard"]}]
}]
creator_paid_tiers - Creator subscription tiers
["REQ", "sub_id", {
"cache": ["creator_paid_tiers", {
"pubkey": "<creator_pubkey>"
}]
}]
#### Media Management
upload - Upload media
["REQ", "sub_id", {
"cache": ["upload", {
"event_from_user": <signed_event_with_base64_data>
}]
}]
upload_chunk - Upload media chunk
["REQ", "sub_id", {
"cache": ["upload_chunk", {
"event_from_user": <signed_event>
}]
}]
upload_complete - Complete chunked upload
["REQ", "sub_id", {
"cache": ["upload_complete", {
"event_from_user": <signed_event>
}]
}]
upload_cancel - Cancel upload
["REQ", "sub_id", {
"cache": ["upload_cancel", {
"event_from_user": <signed_event>
}]
}]
get_media_metadata - Get media metadata
["REQ", "sub_id", {
"cache": ["get_media_metadata", {
"url": "<media_url>"
}]
}]
get_recommended_blossom_servers - Blossom server recommendations
["REQ", "sub_id", {
"cache": ["get_recommended_blossom_servers"]}]
}]
#### Utilities
user_of_ln_address - Get pubkey from Lightning address
["REQ", "sub_id", {
"cache": ["user_of_ln_address", {
"ln_address": "<[email protected]>"
}]
}]
nip19_decode - Decode NIP-19 identifiers
["REQ", "sub_id", {
"cache": ["nip19_decode", {
"identifier": "<npub_or_note...>"
}]
}]
set_last_time_user_was_online - Update online status
["REQ", "sub_id", {
"cache": ["set_last_time_user_was_online", {
"pubkey": "<pubkey>"
}]
}]
trusted_users - Get trusted users
["REQ", "sub_id", {
"cache": ["trusted_users", {
"pubkey": "<pubkey>"
}]
}]
note_mentions - Get note mentions
["REQ", "sub_id", {
"cache": ["note_mentions", {
"event_id": "<event_id>"
}]
}]
note_mentions_count - Count note mentions
["REQ", "sub_id", {
"cache": ["note_mentions_count", {
"event_id": "<event_id>"
}]
}]
find_reposts - Find reposts of event
["REQ", "sub_id", {
"cache": ["find_reposts", {
"event_id": "<event_id>"
}]
}]
user_profile_scored_content - User's top content
["REQ", "sub_id", {
"cache": ["user_profile_scored_content", {
"pubkey": "<pubkey>",
"limit": 5,
"user_pubkey": "<viewer_pubkey>"
}]
}]
user_profile_scored_media_thumbnails - User's top media
["REQ", "sub_id", {
"cache": ["user_profile_scored_media_thumbnails", {
"pubkey": "<pubkey>",
"limit": 5,
"user_pubkey": "<viewer_pubkey>"
}]
}]
CLOSE - Close SubscriptionExactly as in NIP-01:
["CLOSE", <subscription_id>]
Closes an active subscription and stops receiving updates for that subscription ID.
---
Primal extends NIP-01 response messages with many custom event kinds for structured data.
EVENT - Event data
["EVENT", <subscription_id>, <event_json>]
EOSE - End of stored events
["EOSE", <subscription_id>]
OK - Event acceptance status
["OK", <event_id>, <true|false>, <message>]
CLOSED - Subscription closed
["CLOSED", <subscription_id>, <message>]
NOTICE - Human-readable notice
["NOTICE", <message>]
Primal returns special event kinds (10000+) for structured responses:
#### Statistics & Metadata
| Kind | Name | Description |
|------|------|-------------|
| 10000100 | EVENT_STATS | Event statistics (likes, replies, reposts, zaps, score) |
| 10000101 | NET_STATS | Network statistics |
| 10000102 | EXPLORE_LEGEND_COUNTS | User network statistics |
| 10000105 | USER_PROFILE | User profile information |
| 10000108 | USER_SCORES | User scoring data |
| 10000113 | RANGE | Paginated result range metadata |
| 10000115 | EVENT_ACTIONS_COUNT | User's actions on event (liked, reposted, etc.) |
| 10000133 | USER_FOLLOWER_COUNTS | Follower counts for users |
| 10000136 | NOSTR_STATS | Nostr network statistics |
| 10000172 | USER_TRUSTRANKS | User trust ranks |
| 10000174 | ARTICLES_STATS | Article statistics |
#### Direct Messages
| Kind | Name | Description |
|------|------|-------------|
| 10000117 | DIRECTMSG_COUNT | Direct message count (deprecated) |
| 10000118 | DIRECTMSG_COUNTS | Direct message counts by sender |
| 10000134 | DIRECTMSG_COUNT_2 | Extended DM count |
#### Content & Events
| Kind | Name | Description |
|------|------|-------------|
| 10000107 | REFERENCED_EVENT | Referenced/quoted event |
| 10000122 | EVENT_IDS | List of event IDs |
| 10000123 | PARTIAL_RESPONSE | Partial response data |
| 10000127 | EVENT_IMPORT_STATUS | Event import status |
| 10000129 | ZAP_EVENT | Zap event data |
| 10000144 | LONG_FORM_METADATA | Article metadata (word count, etc.) |
#### User Info & Social
| Kind | Name | Description |
|------|------|-------------|
| 10000125 | IS_USER_FOLLOWING | Following status result |
| 10000138 | USER_PUBKEY | User public key mapping |
| 10000157 | USER_FOLLOWER_COUNT_INCREASES | Follower count changes |
| 10000158 | USER_PRIMAL_NAMES | Primal verified names |
| 10000200 | RECOMMENDED_USERS | Recommended users |
#### Relays
| Kind | Name | Description |
|------|------|-------------|
| 10000109 | RELAYS | Relay list with usage stats |
| 10000124 | DEFAULT_RELAYS | Default relay recommendations |
| 10000139 | USER_RELAYS | User's relay list |
| 10000141 | EVENT_RELAYS | Relays where events were seen |
#### Notifications
| Kind | Name | Description |
|------|------|-------------|
| 10000110 | NOTIFICATION | Notification item |
| 10000111 | NOTIFICATIONS_SEEN_UNTIL | Last seen notification timestamp |
| 10000112 | NOTIFICATIONS_SUMMARY | Notification summary (deprecated) |
| 10000132 | NOTIFICATIONS_SUMMARY_2 | Extended notification summary |
#### Content Moderation
| Kind | Name | Description |
|------|------|-------------|
| 10000126 | FILTERLIST | Content filter list |
| 10000130 | FILTERLISTED | Filter status result |
| 10000131 | FILTERING_REASON | Why content was filtered |
| 10000137 | IS_HIDDEN_BY_CONTENT_MODERATION | Content moderation status |
#### Media
| Kind | Name | Description |
|------|------|-------------|
| 10000114 | MEDIA_MAPPING | Media URL mappings |
| 10000119 | MEDIA_METADATA | Media metadata (dimensions, type, etc.) |
| 10000120 | UPLOAD | Upload event |
| 10000121 | UPLOADED | Upload complete with URL |
| 10000135 | UPLOAD_CHUNK | Chunked upload event |
| 10000142 | UPLOADED_2 | Extended upload response with SHA256 |
| 10000175 | RECOMMENDED_BLOSSOM_SERVERS | Blossom server list |
| 10000176 | MEDIA_METADATA_BY_HASH | Media metadata by hash |
#### Hashtags & Links
| Kind | Name | Description |
|------|------|-------------|
| 10000116 | HASHTAGS | Hashtag list (deprecated) |
| 10000160 | HASHTAGS_2 | Extended hashtag data |
| 10000128 | LINK_METADATA | URL metadata/preview |
#### Settings & Config
| Kind | Name | Description |
|------|------|-------------|
| 10000103 | PRIMAL_SETTINGS | Primal-specific settings |
| 10000138 | APP_RELEASES | App release information |
| 10000150 | ADVANCED_FEEDS | Available advanced feeds |
| 10000155 | APP_SUBSETTINGS | App subsettings |
| 30078 | APP_SETTINGS | User app settings (NIP-78) |
#### Feeds & Discovery
| Kind | Name | Description |
|------|------|-------------|
| 10000145 | RECOMMENDED_READS | Recommended articles |
| 10000146 | READS_TOPICS | Article topics |
| 10000148 | FEATURED_AUTHORS | Featured article authors |
| 10000151 | HIGHLIGHT_GROUPS | Highlight groupings |
| 10000152 | READS_FEEDS | Article feed configurations |
| 10000153 | HOME_FEEDS | Home feed configurations |
#### DVM & Metadata
| Kind | Name | Description |
|------|------|-------------|
| 10000156 | DVM_FEED_FOLLOWS_ACTIONS | DVM feed follow actions |
| 10000159 | DVM_FEED_METADATA | DVM feed metadata |
| 10000147 | CREATOR_PAID_TIERS | Creator subscription tiers |
#### Membership
| Kind | Name | Description |
|------|------|-------------|
| 10000162 | SHOW_PRIMAL_SUPPORT | Show Primal support status |
| 10000163 | MEMBERSHIP_MEDIA_MANAGEMENT_STATS | Media storage statistics |
| 10000164 | MEMBERSHIP_MEDIA_MANAGEMENT_UPLOADS | Upload list |
| 10000165 | MEMBERSHIP_RECOVERY_CONTACT_LISTS | Contact list backups |
| 10000166 | MEMBERSHIP_CONTENT_STATS | Content backup stats |
| 10000167 | MEMBERSHIP_CONTENT_REBROADCAST_STATUS | Rebroadcast status |
| 10000168 | MEMBERSHIP_LEGEND_CUSTOMIZATION | Legend customization |
| 10000169 | MEMBERSHIP_COHORTS | Membership cohort data |
| 10000170 | MEMBERSHIP_LEGEND_LEADERBOARD | Legend leaderboard |
| 10000171 | MEMBERSHIP_PREMIUM_LEADERBOARD | Premium leaderboard |
#### Utilities
| Kind | Name | Description |
|------|------|-------------|
| 10000140 | TRUSTED_USERS | Trusted user list |
| 10000143 | NOTE_MENTIONS_COUNT | Note mention count |
| 10000149 | EVENT_BROADCAST_RESPONSES | Broadcast response status |
| 10000173 | NIP19_DECODE_RESULT | NIP-19 decode result |
| 10000177 | INVOICES_TO_ZAP_RECEIPTS | Invoice to zap receipt mapping |
---
1. Core Verbs: Uses REQ and CLOSE verbs exactly as in NIP-01
2. Subscription Model: Maintains the subscription-based architecture
3. Event Format: Standard Nostr events follow NIP-01 structure
4. Response Messages: Uses EVENT, EOSE, OK, CLOSED, NOTICE as in NIP-01
1. No Standard Filters: Primal cache servers do NOT accept NIP-01 filters (ids, authors, kinds, etc.). All queries must use the cache field with named endpoints
2. Cache-Only API: Major addition of cache filter field for accessing pre-computed data through specific endpoints
3. Custom Event Kinds: 70+ custom event kinds (10000100-10000200 range) for structured responses
4. No EVENT Publishing: Primal cache servers are read-only; clients don't publish events via EVENT messages
5. Endpoint-Specific Parameters: Each cache endpoint has its own parameter schema (e.g., user_pubkey for personalization)
6. Async Endpoints: Some endpoints (net_stats, notifications, etc.) marked as async
7. Pagination: Enhanced pagination with offset parameter and RANGE response kind
8. Content Discovery: Extensive trending/discovery features not in base NIP-01
9. Social Graph Analytics: Built-in follower counts, trust ranks, scoring
10. Media Handling: Integrated media upload and processing
11. Membership Features: Premium features and content moderation
12. Advanced Feeds: Complex feed specifications and directives
NIP-01 (Basic Relay):
- Generic event storage and retrieval
- Simple filtering on event properties (by ids, authors, kinds, tags, timestamps)
- No pre-computation or caching
- Stateless event serving
- Accepts standard filter objects
Primal Cache Server:
- Pre-computed analytics and feeds
- Named endpoint system (via cache field)
- Does NOT accept standard NIP-01 filters
- Complex social graph queries
- Trending/scoring algorithms
- User-specific personalization
- Media processing pipeline
- Membership/premium features
- Content moderation integration
---
Standard Nostr events follow NIP-01:
{
"id": "<event_id>",
"pubkey": "<pubkey>",
"created_at": <timestamp>,
"kind": <kind_number>,
"tags": [["tag_name", "value", ...]],
"content": "<content>",
"sig": "<signature>"
}
Below are real examples from Primal cache responses with actual data:
EVENT_STATS (kind 10000100) - Engagement metrics for an event:
{
"kind": 10000100,
"content": "{\"event_id\":\"2357e9afd8f28a8df60a9dc059a5588312c492ecdff1a1d1705dca2a588bba29\",\"likes\":15,\"replies\":4,\"mentions\":0,\"reposts\":8,\"zaps\":1,\"satszapped\":100,\"score\":89,\"score24h\":0}"
}
Fields:
- event_id: The event these stats are for
- likes: Number of kind 7 reactions
- replies: Number of kind 1 replies
- mentions: Times this event was mentioned
- reposts: Number of kind 6 reposts
- zaps: Number of zaps received
- satszapped: Total sats received from zaps
- score: Overall engagement score
- score24h: Score within last 24 hours
USER_PROFILE (kind 10000105) - Extended user profile statistics:
{
"kind": 10000105,
"content": "{\"pubkey\":\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\",\"follows_count\":432,\"followers_count\":4959,\"note_count\":4084,\"long_form_note_count\":9,\"reply_count\":2551,\"time_joined\":1711551550,\"relay_count\":4,\"total_zap_count\":2785,\"total_satszapped\":644685,\"media_count\":774,\"content_zap_count\":9}"
}
Fields:
- pubkey: User's public key
- follows_count: Number of users they follow
- followers_count: Number of followers
- note_count: Total posts (kind 1)
- long_form_note_count: Total articles (kind 30023)
- reply_count: Total replies
- time_joined: Unix timestamp of first activity
- relay_count: Number of relays in their list
- total_zap_count: Total zaps received
- total_satszapped: Total sats received
- media_count: Posts with media
- content_zap_count: Zaps on content
USER_FOLLOWER_COUNTS (kind 10000133) - Follower counts for multiple users:
{
"kind": 10000133,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\":4959}"
}
Maps pubkeys to their follower counts.
USER_SCORES (kind 10000108) - User influence scores:
{
"kind": 10000108,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\":4959}"
}
Maps pubkeys to their influence scores (typically based on followers).
RANGE (kind 10000113) - Pagination metadata:
{
"kind": 10000113,
"content": "{\"since\":1770407244,\"until\":1770439362,\"order_by\":\"created_at\",\"elements\":[\"11db5f1a2dc5f955447ef7e55a0b41e8c8a272c6ac7a111207b1637cd71a6745\",\"72922d75537b51f0b6d5554a0b0173ad53e7b3791feb5e6f9259be0d4cddee20\"]}"
}
Fields:
- since: Start timestamp of range
- until: End timestamp of range
- order_by: Sort field used
- elements: Array of event IDs in the result set
IS_USER_FOLLOWING (kind 10000125) - Follow status check:
{
"kind": 10000125,
"content": "true"
}
Simple boolean string: "true" or "false".
MEDIA_METADATA (kind 10000119) - Media thumbnails and variants:
{
"kind": 10000119,
"content": "{\"resources\":[{\"url\":\"https://media.ditto.pub/3fd58d3db4fdcf40091d69e881242678c8010acc446c3f0d8e95cc9505b12e7a.jpeg\",\"variants\":[{\"s\":\"m\",\"a\":1,\"w\":300,\"h\":300,\"mt\":\"image/webp\",\"url\":\"https://primal.b-cdn.net/media-cache?s=m&a=1&u=https%3A%2F%2Fmedia.ditto.pub%2F...\"}]}]}"
}
Fields:
- resources: Array of media resources
- url: Original media URL
- variants: Array of processed versions
- s: Size (s=small, m=medium, l=large, o=original)
- a: Aspect ratio preserved (1=yes, 0=no)
- w: Width in pixels
- h: Height in pixels
- mt: MIME type
- url: CDN URL for this variant
LINK_METADATA (kind 10000128) - URL preview data:
{
"kind": 10000128,
"content": "{\"event_id\":\"72922d75537b51f0b6d5554a0b0173ad53e7b3791feb5e6f9259be0d4cddee20\",\"resources\":[{\"url\":\"https://www.youtube.com/watch?v=Q0dfVsLD9Fs\",\"icon_url\":\"\",\"md_image\":\"https://i.ytimg.com/vi/Q0dfVsLD9Fs/mqdefault.jpg\",\"md_title\":\"ROSALÍA - OMEGA (Official Video)\",\"md_description\":\"Watch the official video...\"}]}"
}
Fields:
- event_id: Event containing the link
- resources: Array of link previews
- url: The link URL
- icon_url: Site favicon
- md_image: Preview image
- md_title: Page title
- md_description: Page description/summary
ZAP_EVENT (kind 10000129) - Detailed zap information:
{
"kind": 10000129,
"content": "{\"event_id\":\"df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850\",\"created_at\":1770441947,\"sender\":\"7807080250235b13c8fb67aeaf34ad8beea...\",\"receiver\":\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\",\"amount_sats\":21,\"message\":\"https://m.youtube.com/@walkeramerica\"}"
}
Fields:
- event_id: Event that was zapped
- created_at: When the zap was sent
- sender: Zapper's pubkey
- receiver: Recipient's pubkey
- amount_sats: Zap amount in satoshis
- message: Optional message with the zap
MEMBERSHIP_COHORTS (kind 10000169) - Premium membership status:
{
"kind": 10000169,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\":{\"tier\":\"premium\",\"cohort_1\":\"Primal OG\",\"cohort_2\":\"2025\",\"expires_on\":1756684799}}"
}
Fields:
- tier: Membership level ("premium", "legend", etc.)
- cohort_1: Primary cohort label
- cohort_2: Secondary cohort (often year joined)
- expires_on: Unix timestamp when membership expires
DEFAULT_RELAYS (kind 10000124) - Recommended relay list:
{
"kind": 10000124,
"content": "[\"wss://relay.primal.net\",\"wss://nos.lol\",\"wss://njump.me\",\"wss://nostr.t-rg.ws\",\"wss://strfry.openhoofd.nl\",\"wss://nostr.decentony.com\"]"
}
Array of WebSocket relay URLs.
USER_PRIMAL_NAMES (kind 10000158) - Verified Primal usernames:
{
"kind": 10000158,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\":\"alex\"}"
}
Maps pubkeys to their verified Primal usernames ([email protected]).
UPLOADED (kind 10000121) - Media upload result:
{
"kind": 10000121,
"content": "https://media.primal.net/uploads/..."
}
Returns the URL of successfully uploaded media.
---
All examples below are tested against the production Primal cache server at wss://cache.primal.net/v1.
Retrieves complete profile information for a user including metadata, follower counts, and membership status.
Request:
["REQ", "test_profile", {
"cache": ["user_profile", {
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"
}]
}]
Response:
["EVENT", "test_profile", {
"kind": 0,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"created_at": 1765775146,
"content": "{\"about\":\"I create software that empowers people online.\\r\\n\\r\\nI'm vegan btw.\",\"banner\":\"https://media.ditto.pub/d685e0d805f62946a9ae56810ab0fcf6de2b997a57afcf35e4d3a810c3e2b4eb.jpeg\",\"lud16\":\"[email protected]\",\"name\":\"Alex Gleason\",\"nip05\":\"[email protected]\",\"picture\":\"https://media.ditto.pub/3fd58d3db4fdcf40091d69e881242678c8010acc446c3f0d8e95cc9505b12e7a.jpeg\",\"website\":\"https://alexgleason.me/\"}",
"tags": [],
"sig": "..."
}]
["EVENT", "test_profile", {
"kind": 10000105,
"content": "{\"pubkey\":\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\",\"follows_count\":432,\"followers_count\":4959,\"note_count\":4084,\"long_form_note_count\":7,\"reply_count\":2823,\"time_joined\":1668449729,\"total_zap_count\":1179,\"total_satszapped\":4554165}"
}]
["EVENT", "test_profile", {
"kind": 10000119,
"content": "{\"resources\":[{\"url\":\"https://media.ditto.pub/3fd58d3db4fdcf40091d69e881242678c8010acc446c3f0d8e95cc9505b12e7a.jpeg\",\"variants\":[{\"s\":\"m\",\"a\":1,\"w\":300,\"h\":300,\"mt\":\"image/webp\",\"url\":\"https://primal.b-cdn.net/media-cache?s=m&a=1&u=https%3A%2F%2Fmedia.ditto.pub%2F3fd58d3db4fdcf40091d69e881242678c8010acc446c3f0d8e95cc9505b12e7a.jpeg\"}]}]}"
}]
["EVENT", "test_profile", {
"kind": 10000169,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\": {\"tier\": \"premium\", \"cohort_1\": \"Primal OG\", \"cohort_2\": \"2025\", \"expires_on\": 1756684799}}"
}]
["EVENT", "test_profile", {
"kind": 10063,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"created_at": 1716232999,
"content": "",
"tags": [["relays", "wss://relay.mostr.pub", "wss://relay.damus.io", ...]],
"sig": "..."
}]
["EOSE", "test_profile"]
Response includes:
- Kind 0: User metadata (NIP-01)
- Kind 10000105: USER_PROFILE with follower/note counts
- Kind 10000119: MEDIA_METADATA with image variants
- Kind 10000169: MEMBERSHIP_COHORTS showing premium status
- Kind 10063: User relay list (NIP-65)
Retrieves multiple pieces of information for one or more users in a single request.
Request:
["REQ", "test_infos", {
"cache": ["user_infos", {
"pubkeys": ["0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"]
}]
}]
Response:
["EVENT", "test_infos", {
"kind": 0,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"content": "{\"about\":\"I create software that empowers people online...\",...}",
...
}]
["EVENT", "test_infos", {
"kind": 10000108,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\": 4959}"
}]
["EVENT", "test_infos", {
"kind": 10000133,
"content": "{\"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\": 4959}"
}]
["EOSE", "test_infos"]
Response includes:
- Kind 0: User metadata
- Kind 10000108: USER_SCORES (follower-based scoring)
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000119: MEDIA_METADATA for profile images
- Kind 10000169: MEMBERSHIP_COHORTS
Retrieves posts authored by a specific user, limited to 5 results.
Request:
["REQ", "test_feed", {
"cache": ["feed", {
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"notes": "authored",
"limit": 5
}]
}]
Response (abbreviated):
["EVENT", "test_feed", {
"kind": 1,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"created_at": 1770407993,
"content": "https://www.youtube.com/watch?v=Q0dfVsLD9Fs",
"tags": [["proxy", "https://www.youtube.com/watch?v=Q0dfVsLD9Fs", "activitypub"], ["client", "Ditto"]],
"sig": "..."
}]
["EVENT", "test_feed", {
"kind": 6,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"created_at": 1770407784,
"content": "{...}",
"tags": [["e", "2357e9afd8f28a8df60a9dc059a5588312c492ecdff1a1d1705dca2a588bba29"], ...],
"sig": "..."
}]
["EVENT", "test_feed", {
"kind": 1,
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd",
"created_at": 1770407734,
"content": "SecretAsian6 absolute bangers https://www.youtube.com/watch?v=-WbjvylJSnA",
...
}]
["EVENT", "test_feed", {
"kind": 10000100,
"content": "{\"event_id\":\"2357e9afd8f28a8df60a9dc059a5588312c492ecdff1a1d1705dca2a588bba29\",\"likes\":15,\"replies\":4,\"mentions\":0,\"reposts\":8,\"zaps\":1,\"satszapped\":100,\"score\":89,\"score24h\":0}"
}]
["EVENT", "test_feed", {
"kind": 10000113,
"content": "{\"since\": 1770407244, \"until\": 1770439362, \"order_by\": \"created_at\", \"elements\": [\"11db5f1a2dc5f955447ef7e55a0b41e8c8a272c6ac7a111207b1637cd71a6745\", ...]}"
}]
["EVENT", "test_feed", {
"kind": 10000128,
"content": "{\"event_id\": \"72922d75537b51f0b6d5554a0b0173ad53e7b3791feb5e6f9259be0d4cddee20\", \"resources\": [{\"url\": \"https://www.youtube.com/watch?v=Q0dfVsLD9Fs\", \"icon_url\": \"\", \"md_image\": \"https://i.ytimg.com/vi/Q0dfVsLD9Fs/mqdefault.jpg\", \"md_title\": \"ROSALÍA - OMEGA (Official Video)\", \"md_description\": \"...\"}]}"
}]
["EVENT", "test_feed", {
"kind": 10000129,
"content": "{\"event_id\": \"df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850\", \"created_at\": 1770441947, \"sender\": \"7807080250235b13c8fb67aeaf34...\", \"receiver\": \"0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd\", \"amount_sats\": 21, \"message\": \"https://m.youtube.com/@walkeramerica\"}"
}]
["EOSE", "test_feed"]
Response includes:
- Kind 1: Text notes
- Kind 6: Reposts
- Kind 9735: Zap receipts (on user's posts)
- Kind 0: User metadata for authors and mentioned users
- Kind 10000100: EVENT_STATS (likes, replies, zaps counts)
- Kind 10000107: REFERENCED_EVENT (quoted/reposted events)
- Kind 10000113: RANGE (pagination metadata)
- Kind 10000128: LINK_METADATA (URL previews)
- Kind 10000129: ZAP_EVENT (zap details)
- Kind 10000141: EVENT_RELAYS (where events were seen)
Retrieves a conversation thread including the main event, replies, and parent posts.
Request:
["REQ", "test_thread", {
"cache": ["thread_view", {
"event_id": "df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850"
}]
}]
Response:
Returns the target event plus related events (parents, replies, quoted events) along with:
- Kind 1: The note and its replies
- Kind 0: Metadata for all involved users
- Kind 10000100: EVENT_STATS for each event
- Kind 10000107: REFERENCED_EVENT for any quoted posts
- Additional metadata kinds as needed
Search for posts containing "aliens".
Request:
["REQ", "test_search", {
"cache": ["search", {
"query": "aliens",
"limit": 10
}]
}]
Response:
Returns matching posts (kind 1) along with associated metadata, user profiles, and engagement statistics.
Search for users by username or display name.
Request:
["REQ", "test_user_search", {
"cache": ["user_search", {
"query": "jack",
"limit": 10
}]
}]
Response:
Returns:
- Kind 0: User metadata for matching users
- Kind 10000108: USER_SCORES
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000158: USER_PRIMAL_NAMES (verified usernames)
Retrieve globally trending posts from the last 24 hours.
Request:
["REQ", "test_trending", {
"cache": ["explore_global_trending_24h", {}]
}]
Response (abbreviated):
["EVENT", "test_trending", {
"kind": 1,
"pubkey": "f72127cae7d232d87edcf91f88df0d599b5039bfe5f9ff43f4848a0c39e1673e",
"created_at": 1770459290,
"content": "Securely deploy your own clawbot 🦀 in minutes\nhttps://nowclaw.com\nhttps://blosstr.com/4f63db23b53784787b769ecbb5ac7f33b2d1958015acf77169e1cab01b8207af.mp4",
"tags": [["client", "Damus"]],
"sig": "..."
}]
["EVENT", "test_trending", {
"kind": 10000100,
"content": "{\"event_id\":\"998c0b40473a93bd33e8b83ef49b1b1900194f473f75e8faaab5d8256a95d8b9\",\"likes\":82,\"replies\":50,\"mentions\":0,\"reposts\":102,\"zaps\":5,\"satszapped\":21000,\"score\":3421,\"score24h\":3421}"
}]
["EVENT", "test_trending", {
"kind": 10000119,
"content": "{\"thumbnails\":{\"https://blosstr.com/4f63db23b53784787b769ecbb5ac7f33b2d1958015acf77169e1cab01b8207af.mp4\":\"https://r2.primal.net/cache/a/64/7a/a647a41db4a...\"}}"
}]
["EVENT", "test_trending", {
"kind": 10000128,
"content": "{\"event_id\":\"998c0b40473a93bd33e8b83ef49b1b1900194f473f75e8faaab5d8256a95d8b9\",\"resources\":[{\"url\":\"https://nowclaw.com\",\"mimetype\":\"text/html\",\"md_title\":\"NowClaw - Deploy Your Own Nostr Bot\",\"md_description\":\"...\",\"icon_url\":\"...\"}]}"
}]
["EOSE", "test_trending"]
Retrieve users who liked a specific post.
Request:
["REQ", "test_likes", {
"cache": ["event_actions", {
"event_id": "df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850",
"kind": 7,
"limit": 20
}]
}]
Response (abbreviated):
["EVENT", "test_likes", {
"kind": 7,
"pubkey": "b1d620b63be952e61a4ecd3d76f9abc635cfb5b3ddade661c53835c77ea4c83c",
"created_at": 1770480478,
"content": "+",
"tags": [
["e", "df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850"],
["p", "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"]
],
"sig": "..."
}]
["EVENT", "test_likes", {
"kind": 7,
"pubkey": "6597a1668c0436f5a7de6dd0da9b355eea0e62693a65c3d90a055eb9e0dd6fe1",
"created_at": 1770449193,
"content": "+",
"tags": [...],
"sig": "..."
}]
["EVENT", "test_likes", {
"kind": 0,
"pubkey": "b1d620b63be952e61a4ecd3d76f9abc635cfb5b3ddade661c53835c77ea4c83c",
"content": "{\"name\":\"User Name\",\"about\":\"...\"}",
...
}]
["EOSE", "test_likes"]
Response includes:
- Kind 7: Like reactions
- Kind 0: User metadata for users who liked the post
- Additional metadata kinds as needed
Other action kinds:
- kind: 1 - Replies to the event
- kind: 6 - Reposts/quotes
- kind: 9735 - Zap receipts
Get posts from various trending/scoring algorithms.
Request (trending_24h):
["REQ", "test_scored", {
"cache": ["scored", {
"selector": "trending_24h"
}]
}]
Request (mostzapped_4h):
["REQ", "test_scored", {
"cache": ["scored", {
"selector": "mostzapped_4h"
}]
}]
Available selectors:
- trending_24h, trending_12h, trending_4h, trending_1h - Trending by engagement
- mostzapped_24h, mostzapped_12h, mostzapped_4h, mostzapped_1h - Most zapped posts
- gm_trending_24h, gm_trending_12h, etc. - GM-specific trending
- classic_trending_24h, etc. - Classic algorithm
Response:
Similar to explore_global_trending_24h, returns posts with full metadata, stats, media info, etc.
Retrieve a list of users who follow a specific account.
Request:
["REQ", "test_followers", {
"cache": ["user_followers", {
"pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
"limit": 20
}]
}]
Response:
Returns:
- Kind 0: User metadata for each follower
- Kind 10000108: USER_SCORES
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000119: MEDIA_METADATA (profile images)
- Kind 10000158: USER_PRIMAL_NAMES
- Kind 10000169: MEMBERSHIP_COHORTS
- Kind 10063: User relay lists
Check if one user follows another.
Request:
["REQ", "test_is_following", {
"cache": ["is_user_following", {
"pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
"user_pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"
}]
}]
Response:
["EVENT", "test_is_following", {
"kind": 10000125,
"content": "true"
}]
["EOSE", "test_is_following"]
Returns a simple boolean string ("true" or "false") in the content field.
Retrieve one or more events by their IDs with extended metadata.
Request:
["REQ", "test_events", {
"cache": ["events", {
"event_ids": ["df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850"],
"extended_response": true
}]
}]
Response:
Returns:
- Kind 1: The requested event(s)
- Kind 0: User metadata for event authors
- Kind 10000100: EVENT_STATS (engagement metrics)
- Kind 10000119: MEDIA_METADATA
- Kind 10000129: ZAP_EVENT (zaps on the event)
- Kind 10000141: EVENT_RELAYS (where event was seen)
- Kind 10063: User relay lists
Retrieve Primal's recommended default relays for new users.
Request:
["REQ", "test_default_relays", {
"cache": ["get_default_relays"]
}]
Response:
["EVENT", "test_default_relays", {
"kind": 10000124,
"content": "[\"wss://relay.primal.net\",\"wss://nos.lol\",\"wss://njump.me\",\"wss://nostr.t-rg.ws\",\"wss://strfry.openhoofd.nl\",\"wss://nostr.decentony.com\"]"
}]
["EOSE", "test_default_relays"]
Retrieve a user's mute list for content moderation.
Request:
["REQ", "test_mutelist", {
"cache": ["mutelist", {
"pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2"
}]
}]
Response:
Returns:
- Kind 10000: Mute list event containing muted pubkeys and event IDs
- Kind 0: User metadata for muted users
- Kind 10000108: USER_SCORES for muted users
Get trending/recent zaps across the network.
Request:
["REQ", "test_explore_zaps", {
"cache": ["explore_zaps", {
"limit": 10
}]
}]
Response (abbreviated):
Returns:
- Kind 9735: Zap receipt events
- Kind 1: The posts that were zapped
- Kind 0: User metadata for zappers and recipients
- Kind 10000100: EVENT_STATS for zapped posts
- Kind 10000129: ZAP_EVENT (detailed zap information)
- Kind 10000119: MEDIA_METADATA
- Kind 10000158: USER_PRIMAL_NAMES
- Kind 10000169: MEMBERSHIP_COHORTS
Discover trending or recommended users.
Request:
["REQ", "test_explore_people", {
"cache": ["explore_people", {
"limit": 10
}]
}]
Response:
Returns:
- Kind 0: User metadata for recommended users
- Kind 10000108: USER_SCORES
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000119: MEDIA_METADATA (profile images)
- Kind 10000113: RANGE (pagination metadata)
- Kind 10063: User relay lists
Get trending posts with media content (images/videos).
Request:
["REQ", "test_explore_media", {
"cache": ["explore_media", {
"limit": 10
}]
}]
Response:
Returns:
- Kind 1: Posts containing media
- Kind 0: User metadata for post authors
- Kind 10000100: EVENT_STATS
- Kind 10000119: MEDIA_METADATA (thumbnails, dimensions, etc.)
- Kind 10000128: LINK_METADATA (for linked content)
- Kind 10000113: RANGE
Retrieve all replies to a specific event.
Request:
["REQ", "test_replies", {
"cache": ["event_actions", {
"event_id": "df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850",
"kind": 1,
"limit": 20
}]
}]
Response:
Returns:
- Kind 1: Reply posts that reference the target event
- Kind 0: User metadata for reply authors
- Kind 10000119: MEDIA_METADATA
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10063: User relay lists
Retrieve all zaps sent to a specific event.
Request:
["REQ", "test_zaps", {
"cache": ["event_actions", {
"event_id": "df670a0c011959f432b63f0458202f3f985f3fd3765acc788a3276d7229d6850",
"kind": 9735,
"limit": 20
}]
}]
Response:
Returns:
- Kind 9735: Zap receipt events
- Kind 0: User metadata for zappers
- Kind 10000108: USER_SCORES
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000129: ZAP_EVENT (detailed zap info including amount)
Retrieve a user's full contact/follow list.
Request:
["REQ", "test_contacts", {
"cache": ["contact_list", {
"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"
}]
}]
Response:
Returns:
- Kind 3: Contact list event with follows
- Kind 0: User metadata for all follows (can be 100s-1000s)
- Kind 10000108: USER_SCORES (aggregated)
- Kind 10000119: MEDIA_METADATA for all follow profiles
- Kind 10000133: USER_FOLLOWER_COUNTS
- Kind 10000158: USER_PRIMAL_NAMES
- Kind 10063: User relay lists for follows
Note: This can return very large responses (1MB+) for users with many follows.
Retrieve posts from users that a specific account follows.
Request:
["REQ", "test_feed_follows", {
"cache": ["feed", {
"pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
"notes": "follows",
"limit": 10
}]
}]
Response:
Returns:
- Kind 1: Text posts from followed users
- Kind 6: Reposts from followed users
- Kind 9735: Zap receipts
- Kind 0: User metadata for post authors
- Kind 10000100: EVENT_STATS
- Kind 10000113: RANGE (pagination)
- Kind 10000119: MEDIA_METADATA
- Kind 10000128: LINK_METADATA
- Kind 10000129: ZAP_EVENT
- Kind 10000158: USER_PRIMAL_NAMES
- Kind 10000169: MEMBERSHIP_COHORTS
Request:
["CLOSE", "test_profile"]
No response required per NIP-01. The server stops sending events for this subscription ID.
---
You can test the Primal WebSocket API using command-line tools or scripts. Here are a few approaches:
# Install wscat
npm install -g wscat
Connect and send a request
echo '["REQ", "test1", {"cache": ["user_profile", {"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"}]}]' | \
wscat -c wss://cache.primal.net/v1
const socket = new WebSocket('wss://cache.primal.net/v1');
socket.onopen = () => {
socket.send(JSON.stringify([
"REQ",
"my_sub",
{"cache": ["user_profile", {"pubkey": "0461fcbecc4c3374439932d6b8f11269ccdb7cc973ad7a50ae362db135a474dd"}]}
]));
};
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg);
if (msg[0] === 'EOSE') {
socket.close();
}
};
socket.onerror = (error) => {
console.error('WebSocket error:', error);
};
socket.onclose = () => {
console.log('Connection closed');
};
Primal responses typically include:
1. Main Content Events: The actual data you requested (kind 0, 1, 6, etc.)
2. Metadata Events: Enrichment data about the content (10000xxx kinds)
3. RANGE Event (kind 10000113): Pagination info with since, until, and elements array
4. EOSE: End of stored events marker
Example response flow for user_profile:
EVENT (kind 0) → User metadata
EVENT (kind 10000105) → Profile stats (followers, notes count)
EVENT (kind 10000119) → Media metadata (profile images)
EVENT (kind 10000169) → Membership status
EVENT (kind 10063) → User relay list
EOSE → Done
---
1. Single Connection: Open one WebSocket per relay and reuse for all subscriptions
2. Unique Subscription IDs: Use random, unique strings for each subscription
3. Handle EOSE: Wait for EOSE before considering initial query complete
4. Pagination: Use offset and limit for large result sets
5. User Context: Include user_pubkey when available for personalized results
6. Rate Limiting: Respect server limits (max 1000 for most limit parameters)
7. Time Ranges: Use since/until for efficient time-based queries
8. Event Validation: Validate event signatures and structure
9. Reconnection: Implement exponential backoff for reconnections
10. Error Handling: Handle CLOSED and NOTICE messages appropriately
---
When displaying a user profile, you typically need:
// 1. Get complete profile
["REQ", "profile", {"cache": ["user_profile", {"pubkey": "<pubkey>"}]}]
// 2. Get user's posts
["REQ", "posts", {"cache": ["feed", {
"pubkey": "<pubkey>",
"notes": "authored",
"limit": 20
}]}]
// 3. Get follower information
["REQ", "followers", {"cache": ["user_followers", {
"pubkey": "<pubkey>",
"limit": 100
}]}]
For a personalized feed showing posts from users someone follows:
["REQ", "home_feed", {"cache": ["feed", {
"pubkey": "<user_pubkey>",
"notes": "follows",
"limit": 50,
"user_pubkey": "<user_pubkey>" // For personalization
}]}]
Use offset and limit for pagination:
// Page 1
["REQ", "page1", {"cache": ["feed", {
"pubkey": "<pubkey>",
"notes": "authored",
"limit": 20,
"offset": 0
}]}]
// Page 2
["REQ", "page2", {"cache": ["feed", {
"pubkey": "<pubkey>",
"notes": "authored",
"limit": 20,
"offset": 20
}]}]
The RANGE event (kind 10000113) in responses contains the actual range of data returned:
{
"kind": 10000113,
"content": "{\"since\": 1770407244, \"until\": 1770439362, \"order_by\": \"created_at\", \"elements\": [\"event_id1\", \"event_id2\", ...]}"
}
Keep a subscription open to receive real-time updates:
const socket = new WebSocket('wss://cache.primal.net/v1');
socket.onopen = () => {
// Subscribe to notifications
socket.send(JSON.stringify([
"REQ",
"notifications",
{"cache": ["get_notifications", {
"pubkey": "<user_pubkey>",
"limit": 100
}]}
]));
};
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg[0] === 'EVENT') {
// Handle new notification
console.log('New notification:', msg);
} else if (msg[0] === 'EOSE') {
console.log('Initial notifications loaded');
// Keep connection open - new events will arrive as they happen
}
};
// Close when done:
socket.send(JSON.stringify(["CLOSE", "notifications"]));
socket.close();
---
The server may close subscriptions with CLOSED messages:
["CLOSED", "sub1", "error: could not connect to the database"]
["CLOSED", "sub2", "unsupported: filter contains unknown elements"]
["CLOSED", "sub3", "rate-limited: slow down there chief"]
Common error prefixes:
- error: Server error
- unsupported: Unsupported filter/feature
- rate-limited: Too many requests
- invalid: Invalid parameters
- blocked: Access denied
---
- Max limit parameter: 1000 (most endpoints)
- Max subscription ID length: 64 characters
- Max upload size: Configurable (default varies)
- Connection limits: May vary by server configuration
- Some endpoints have specific lower limits (noted in documentation)
---
- NIP-01 Specification
- Primal GitHub Repository
- Primal Cache Endpoint: wss://cache.primal.net/v1
---
See individual endpoint documentation above for:
- 140+ cache endpoints
- 70+ custom event kinds
- Standard NIP-01 message types
- Extended filter parameters
- Response data structures