Skip to content

API Reference

This document provides a comprehensive reference for all API endpoints exposed by Shugur Relay.

Overview

Shugur Relay exposes several types of APIs:

  1. WebSocket API - Core Nostr protocol implementation
  2. HTTP REST API - Management and monitoring endpoints
  3. Metrics API - Prometheus metrics endpoint
  4. Web Dashboard - Browser-based interface

WebSocket API (Nostr Protocol)

The main relay functionality follows the Nostr protocol specification.

Endpoint

ws://localhost:8080/
wss://relay.example.com/

Protocol Overview

The WebSocket API implements the Nostr protocol using JSON messages. All messages are JSON arrays where the first element is a command string.

Client to Relay Messages

EVENT

Submit a new event to the relay.

["EVENT", <event>]

Example:

[
"EVENT",
{
"id": "4376c65d2f232afbe9b882a35baa4f6fe8667c4e684749af565f981833ed6a65",
"pubkey": "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93",
"created_at": 1673347337,
"kind": 1,
"tags": [],
"content": "Walled gardens became prisons, and nostr is the first step towards tearing down the prison walls.",
"sig": "908a15e46fb4d8675bab026fc230a0e3542bfade63da02d542fb78b2a8513fcd0092619a2c8c1221e581946e0191f2af505dfdf8657a414dbca329186f009262"
}
]

Response:

["OK", <event_id>, <accepted>, <message>]

REQ

Start a subscription to receive events.

["REQ", <subscription_id>, <filters>...]

Example:

[
"REQ",
"my-subscription",
{
"authors": ["6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93"],
"kinds": [1],
"limit": 10
}
]

Response: Stream of EVENT messages followed by EOSE.

CLOSE

Close a subscription.

["CLOSE", <subscription_id>]

Example:

["CLOSE", "my-subscription"]

COUNT (NIP-45)

Request event count for filters.

["COUNT", <subscription_id>, <filters>...]

Example:

[
"COUNT",
"count-sub",
{
"authors": ["6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93"],
"kinds": [1]
}
]

Response:

["COUNT", <subscription_id>, {"count": <number>}]

Relay to Client Messages

EVENT

Event matching a subscription.

["EVENT", <subscription_id>, <event>]

EOSE

End of stored events for a subscription.

["EOSE", <subscription_id>]

CLOSED

Subscription was closed by the relay.

["CLOSED", <subscription_id>, <message>]

NOTICE

Informational message from relay.

["NOTICE", <message>]

OK

Response to EVENT submission.

["OK", <event_id>, <accepted>, <message>]

Event Filters

Filters are used in REQ and COUNT messages to specify which events to retrieve.

Filter Fields

FieldTypeDescription
idsarray of stringsEvent IDs
authorsarray of stringsPubkeys of event authors
kindsarray of integersEvent kinds
#<tag>array of stringsTag values (e.g., #e, #p)
sinceintegerEvents after this timestamp
untilintegerEvents before this timestamp
limitintegerMaximum number of events
searchstringFull-text search (NIP-50)

Filter Examples

Latest 10 text notes:

{
"kinds": [1],
"limit": 10
}

Events by specific author:

{
"authors": ["pubkey_hex"],
"limit": 50
}

Events with specific tag:

{
"#p": ["referenced_pubkey"],
"limit": 20
}

Search for text:

{
"kinds": [1],
"search": "nostr protocol",
"limit": 10
}

HTTP REST API

Relay Information (NIP-11)

GET /

Returns relay metadata when accessed with appropriate headers.

Request Headers:

Accept: application/nostr+json

Response:

{
"name": "Shugur Relay",
"description": "High-performance Nostr relay",
"pubkey": "relay_pubkey_hex",
"contact": "admin@example.com",
"supported_nips": [1, 2, 3, 4, 9, 11, 15, 16, 17, 20, 22, 23, 24, 25, 26, 28, 33, 40, 44, 50, 59, 65, 78],
"software": "https://github.com/Shugur-Network/relay",
"version": "1.0.0",
"limitation": {
"max_message_length": 2048,
"max_subscriptions": 10,
"max_filters": 100,
"max_event_tags": 100,
"auth_required": false,
"payment_required": false
}
}

API Endpoints

GET /api/info

Returns relay information in JSON format.

Response:

{
"name": "Shugur Relay",
"description": "High-performance Nostr relay",
"version": "1.0.0",
"contact": "admin@example.com",
"pubkey": "relay_pubkey_hex",
"supported_nips": [1, 2, 3, 4, 9, 11, 15, 16, 17, 20, 22, 23, 24, 25, 26, 28, 33, 40, 44, 50, 59, 65, 78]
}

GET /api/stats

Returns current relay statistics.

Response:

{
"stats": {
"active_connections": 42,
"messages_processed": 1234567,
"events_stored": 98765
},
"uptime": "2d 5h 30m"
}

GET /api/cluster

Returns CockroachDB cluster information.

Query Parameters:

  • type=health - Returns cluster health information

Response (cluster info):

{
"is_cluster": true,
"node_count": 3,
"cluster_version": "v23.1.0",
"nodes": [
{
"node_id": 1,
"address": "node1.example.com:26257",
"is_live": true,
"is_available": true
}
]
}

Response (health check):

{
"healthy": true,
"details": {
"nodes_live": 3,
"nodes_total": 3,
"replication_status": "healthy"
}
}

Metrics API (Prometheus)

Endpoint

GET http://localhost:2112/metrics

Available Metrics

Connection Metrics

  • relay_active_connections - Current number of active WebSocket connections
  • relay_total_connections - Total connections since start
  • relay_connection_duration_seconds - Connection duration histogram

Event Metrics

  • relay_events_received_total - Total events received
  • relay_events_stored_total - Total events stored
  • relay_events_rejected_total - Total events rejected
  • relay_event_processing_duration_seconds - Event processing time

Request Metrics

  • relay_http_requests_total - Total HTTP requests
  • relay_http_request_duration_seconds - HTTP request duration
  • relay_websocket_messages_total - Total WebSocket messages

Database Metrics

  • relay_db_connections_total - Database connection status
  • relay_db_operations_total - Database operations by type
  • relay_db_errors_total - Database errors by type

System Metrics

  • relay_uptime_seconds - Relay uptime in seconds
  • relay_memory_usage_bytes - Memory usage
  • relay_goroutines_total - Number of goroutines

Web Dashboard

Endpoint

GET http://localhost:8080/

The web dashboard provides a browser-based interface for monitoring the relay.

Features

  • Real-time Statistics - Live connection and event counters
  • Relay Information - Configuration and metadata display
  • Performance Metrics - Charts and graphs (if enabled)
  • Cluster Status - CockroachDB cluster information
  • Recent Events - Latest events processed

Error Responses

WebSocket Errors

NOTICE Messages

Informational messages sent to clients:

["NOTICE", "rate limit exceeded"]
["NOTICE", "event rejected: invalid signature"]
["NOTICE", "subscription limit reached"]
["NOTICE", "connection will be closed due to policy violation"]

CLOSED Messages

Subscription closed by relay:

["CLOSED", "subscription_id", "rate limit exceeded"]
["CLOSED", "subscription_id", "invalid filter"]
["CLOSED", "subscription_id", "relay overloaded"]

OK Messages (Event Rejection)

["OK", "event_id", false, "invalid: signature verification failed"]
["OK", "event_id", false, "blocked: pubkey is blacklisted"]
["OK", "event_id", false, "rate-limited: too many events"]

HTTP Error Responses

400 Bad Request

{
"error": "invalid request format",
"message": "request body must be valid JSON"
}

429 Too Many Requests

{
"error": "rate limit exceeded",
"message": "too many requests, try again later",
"retry_after": 60
}

500 Internal Server Error

{
"error": "internal server error",
"message": "database connection failed"
}

Rate Limiting

Connection Limits

  • Maximum concurrent connections per IP
  • Progressive banning for violations
  • Burst allowance for brief traffic spikes

Request Limits

  • Events per second per connection
  • Requests per second per connection
  • Content length limits

Rate Limit Headers

HTTP responses include rate limit information:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640995200

Client Libraries

JavaScript/TypeScript

const relay = new WebSocket('ws://localhost:8080');
// Send subscription
relay.send(JSON.stringify([
"REQ",
"sub1",
{"kinds": [1], "limit": 10}
]));
// Handle messages
relay.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};

Python

import websocket
import json
def on_message(ws, message):
data = json.loads(message)
print("Received:", data)
ws = websocket.WebSocketApp("ws://localhost:8080",
on_message=on_message)
ws.run_forever()

Go

package main
import (
"github.com/gorilla/websocket"
"github.com/nbd-wtf/go-nostr"
)
func main() {
relay, err := nostr.RelayConnect(context.Background(), "ws://localhost:8080")
if err != nil {
panic(err)
}
// Subscribe to events
sub := relay.Subscribe(context.Background(), nostr.Filters{
{Kinds: []int{1}, Limit: 10},
})
for ev := range sub.Events {
fmt.Printf("Received event: %s\n", ev.Content)
}
}

Testing

WebSocket Testing

Terminal window
# Install wscat
npm install -g wscat
# Connect to relay
wscat -c ws://localhost:8080
# Send a REQ message
["REQ", "test", {"kinds": [1], "limit": 1}]

HTTP Testing

Terminal window
# Test relay info
curl -H "Accept: application/nostr+json" http://localhost:8080/
# Test statistics
curl http://localhost:8080/api/stats
# Test cluster info
curl http://localhost:8080/api/cluster

Best Practices

Client Implementation

  1. Handle reconnections - Implement automatic reconnection logic
  2. Respect rate limits - Monitor rate limit headers and back off when needed
  3. Use appropriate filters - Limit subscriptions to reduce server load
  4. Close unused subscriptions - Send CLOSE messages when done

Server Integration

  1. Monitor metrics - Use Prometheus metrics for monitoring
  2. Configure rate limits - Set appropriate limits for your use case
  3. Use HTTPS/WSS - Always use TLS in production
  4. Regular backups - Backup your database regularly

Performance Optimization

  1. Use specific filters - Avoid overly broad subscriptions
  2. Limit event size - Keep event content reasonable
  3. Monitor connections - Track connection patterns and adjust limits
  4. Database tuning - Optimize database configuration for your workload