996 lines
22 KiB
Markdown
996 lines
22 KiB
Markdown
# C-Relay API Documentation
|
|
|
|
Complete API reference for the C-Relay event-based administration system and advanced features.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Authentication](#authentication)
|
|
- [Admin API](#admin-api)
|
|
- [Event Structure](#event-structure)
|
|
- [Configuration Management](#configuration-management)
|
|
- [Auth Rules Management](#auth-rules-management)
|
|
- [System Commands](#system-commands)
|
|
- [Database Queries](#database-queries)
|
|
- [Configuration Reference](#configuration-reference)
|
|
- [Real-time Monitoring](#real-time-monitoring)
|
|
- [Direct Message Admin](#direct-message-admin)
|
|
- [Response Formats](#response-formats)
|
|
- [Error Handling](#error-handling)
|
|
- [Examples](#examples)
|
|
|
|
## Overview
|
|
|
|
C-Relay uses an innovative **event-based administration system** where all configuration and management commands are sent as cryptographically signed Nostr events. This provides:
|
|
|
|
- **Cryptographic security**: All commands must be signed with the admin private key
|
|
- **Audit trail**: Complete history of all administrative actions
|
|
- **Real-time updates**: Configuration changes applied instantly
|
|
- **Standard protocol**: Uses Nostr events, no custom protocols
|
|
- **NIP-44 encryption**: All admin commands and responses are encrypted
|
|
|
|
### Key Concepts
|
|
|
|
1. **Admin Keypair**: Generated on first startup, used to sign all admin commands
|
|
2. **Relay Keypair**: The relay's identity on the Nostr network
|
|
3. **Admin Events**: Kind 23456 events with NIP-44 encrypted commands
|
|
4. **Response Events**: Kind 23457 events with NIP-44 encrypted responses
|
|
5. **Event-Based Config**: All settings stored as events in the database
|
|
|
|
## Authentication
|
|
|
|
### Admin Private Key
|
|
|
|
The admin private key is displayed **only once** during first startup:
|
|
|
|
```
|
|
========================================
|
|
IMPORTANT: SAVE THIS ADMIN PRIVATE KEY
|
|
========================================
|
|
Admin Private Key: nsec1abc123...
|
|
Admin Public Key: npub1def456...
|
|
========================================
|
|
```
|
|
|
|
**Critical**: Save this key immediately. It cannot be recovered and is required for all administrative operations.
|
|
|
|
### Secure Storage
|
|
|
|
Store the admin private key securely:
|
|
|
|
```bash
|
|
# Environment variable
|
|
export C_RELAY_ADMIN_KEY="nsec1abc123..."
|
|
|
|
# Secure file
|
|
echo "nsec1abc123..." > ~/.c-relay-admin
|
|
chmod 600 ~/.c-relay-admin
|
|
|
|
# Password manager (recommended)
|
|
# Store in 1Password, Bitwarden, etc.
|
|
```
|
|
|
|
### Key Loss Recovery
|
|
|
|
If you lose the admin private key:
|
|
|
|
1. Stop the relay
|
|
2. Delete the database file (`*.db`)
|
|
3. Restart the relay (generates new keys)
|
|
4. **Note**: This deletes all events and configuration
|
|
|
|
## Admin API
|
|
|
|
### Event Structure
|
|
|
|
All admin commands use the same event structure with NIP-44 encrypted content.
|
|
|
|
#### Admin Command Event (Kind 23456)
|
|
|
|
```json
|
|
{
|
|
"id": "computed_event_id",
|
|
"pubkey": "admin_public_key_hex",
|
|
"created_at": 1234567890,
|
|
"kind": 23456,
|
|
"content": "AqHBUgcM7dXFYLQuDVzGwMST1G8jtWYyVvYxXhVGEu4nAb4LVw...",
|
|
"tags": [
|
|
["p", "relay_public_key_hex"]
|
|
],
|
|
"sig": "event_signature"
|
|
}
|
|
```
|
|
|
|
**Fields**:
|
|
- `kind`: Must be `23456` for admin commands
|
|
- `pubkey`: Admin public key (hex format)
|
|
- `content`: NIP-44 encrypted JSON array containing the command
|
|
- `tags`: Must include `["p", "relay_pubkey"]` tag
|
|
- `sig`: Valid signature from admin private key
|
|
|
|
#### Encrypted Content Format
|
|
|
|
The `content` field contains a NIP-44 encrypted JSON array:
|
|
|
|
```json
|
|
["command_name", "param1", "param2", ...]
|
|
```
|
|
|
|
Examples:
|
|
```json
|
|
["config_query", "all"]
|
|
["config_update", [{"key": "relay_name", "value": "My Relay", ...}]]
|
|
["blacklist", "pubkey", "abc123..."]
|
|
["auth_query", "all"]
|
|
["sql_query", "SELECT * FROM events LIMIT 10"]
|
|
```
|
|
|
|
#### Admin Response Event (Kind 23457)
|
|
|
|
```json
|
|
{
|
|
"id": "response_event_id",
|
|
"pubkey": "relay_public_key_hex",
|
|
"created_at": 1234567890,
|
|
"kind": 23457,
|
|
"content": "BpKCVhfN8eYtRmPqSvWxZnMkL2gHjUiOp3rTyEwQaS5dFg...",
|
|
"tags": [
|
|
["p", "admin_public_key_hex"],
|
|
["e", "request_event_id"]
|
|
],
|
|
"sig": "response_signature"
|
|
}
|
|
```
|
|
|
|
**Fields**:
|
|
- `kind`: Always `23457` for admin responses
|
|
- `pubkey`: Relay public key (hex format)
|
|
- `content`: NIP-44 encrypted JSON response object
|
|
- `tags`: Includes `["p", "admin_pubkey"]` and optionally `["e", "request_id"]`
|
|
- `sig`: Valid signature from relay private key
|
|
|
|
### Configuration Management
|
|
|
|
#### Query All Configuration
|
|
|
|
**Command**:
|
|
```json
|
|
["config_query", "all"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "config_all",
|
|
"total_results": 27,
|
|
"timestamp": 1234567890,
|
|
"data": [
|
|
{
|
|
"key": "relay_name",
|
|
"value": "C-Relay",
|
|
"data_type": "string",
|
|
"category": "relay",
|
|
"description": "Relay name displayed in NIP-11"
|
|
},
|
|
{
|
|
"key": "auth_enabled",
|
|
"value": "false",
|
|
"data_type": "boolean",
|
|
"category": "auth",
|
|
"description": "Enable whitelist/blacklist authentication"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Update Configuration
|
|
|
|
**Command**:
|
|
```json
|
|
["config_update", [
|
|
{
|
|
"key": "relay_name",
|
|
"value": "My Awesome Relay",
|
|
"data_type": "string",
|
|
"category": "relay"
|
|
},
|
|
{
|
|
"key": "max_subscriptions_per_client",
|
|
"value": "50",
|
|
"data_type": "integer",
|
|
"category": "limits"
|
|
}
|
|
]]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "config_update",
|
|
"status": "success",
|
|
"total_results": 2,
|
|
"timestamp": 1234567890,
|
|
"data": [
|
|
{
|
|
"key": "relay_name",
|
|
"value": "My Awesome Relay",
|
|
"status": "updated"
|
|
},
|
|
{
|
|
"key": "max_subscriptions_per_client",
|
|
"value": "50",
|
|
"status": "updated"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Auth Rules Management
|
|
|
|
#### Add Blacklist Rule
|
|
|
|
**Command**:
|
|
```json
|
|
["blacklist", "pubkey", "abc123def456..."]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "auth_add",
|
|
"status": "success",
|
|
"message": "Blacklist rule added successfully",
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
#### Add Whitelist Rule
|
|
|
|
**Command**:
|
|
```json
|
|
["whitelist", "pubkey", "def456abc123..."]
|
|
```
|
|
|
|
#### Delete Auth Rule
|
|
|
|
**Command**:
|
|
```json
|
|
["delete_auth_rule", "blacklist", "pubkey", "abc123def456..."]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "auth_delete",
|
|
"status": "success",
|
|
"message": "Auth rule deleted successfully",
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
#### Query All Auth Rules
|
|
|
|
**Command**:
|
|
```json
|
|
["auth_query", "all"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "auth_rules_all",
|
|
"total_results": 5,
|
|
"timestamp": 1234567890,
|
|
"data": [
|
|
{
|
|
"rule_type": "blacklist",
|
|
"pattern_type": "pubkey",
|
|
"pattern_value": "abc123...",
|
|
"action": "deny"
|
|
},
|
|
{
|
|
"rule_type": "whitelist",
|
|
"pattern_type": "pubkey",
|
|
"pattern_value": "def456...",
|
|
"action": "allow"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Query Specific Rule Type
|
|
|
|
**Command**:
|
|
```json
|
|
["auth_query", "whitelist"]
|
|
```
|
|
|
|
#### Query Specific Pattern
|
|
|
|
**Command**:
|
|
```json
|
|
["auth_query", "pattern", "abc123..."]
|
|
```
|
|
|
|
### System Commands
|
|
|
|
#### System Status
|
|
|
|
**Command**:
|
|
```json
|
|
["system_command", "system_status"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "system_status",
|
|
"timestamp": 1234567890,
|
|
"status": "running",
|
|
"uptime_seconds": 86400,
|
|
"version": "0.6.0",
|
|
"relay_pubkey": "relay_public_key_hex",
|
|
"database_size_bytes": 10485760,
|
|
"total_events": 15432,
|
|
"active_connections": 42,
|
|
"active_subscriptions": 156
|
|
}
|
|
```
|
|
|
|
#### Clear All Auth Rules
|
|
|
|
**Command**:
|
|
```json
|
|
["system_command", "clear_all_auth_rules"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "system_command",
|
|
"status": "success",
|
|
"message": "All auth rules cleared",
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
#### Database Statistics
|
|
|
|
**Command**:
|
|
```json
|
|
["stats_query"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "stats_query",
|
|
"timestamp": 1234567890,
|
|
"database_size_bytes": 10485760,
|
|
"total_events": 15432,
|
|
"database_created_at": 1234567800,
|
|
"latest_event_at": 1234567890,
|
|
"event_kinds": [
|
|
{
|
|
"kind": 1,
|
|
"count": 12000,
|
|
"percentage": 77.8
|
|
},
|
|
{
|
|
"kind": 0,
|
|
"count": 2500,
|
|
"percentage": 16.2
|
|
}
|
|
],
|
|
"time_stats": {
|
|
"total": 15432,
|
|
"last_24h": 234,
|
|
"last_7d": 1456,
|
|
"last_30d": 5432
|
|
},
|
|
"top_pubkeys": [
|
|
{
|
|
"pubkey": "abc123...",
|
|
"event_count": 1234,
|
|
"percentage": 8.0
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Database Queries
|
|
|
|
#### SQL Query Command
|
|
|
|
Execute read-only SQL queries against the relay database.
|
|
|
|
**Command**:
|
|
```json
|
|
["sql_query", "SELECT * FROM events ORDER BY created_at DESC LIMIT 10"]
|
|
```
|
|
|
|
**Response** (decrypted):
|
|
```json
|
|
{
|
|
"query_type": "sql_query",
|
|
"request_id": "request_event_id",
|
|
"timestamp": 1234567890,
|
|
"query": "SELECT * FROM events ORDER BY created_at DESC LIMIT 10",
|
|
"execution_time_ms": 45,
|
|
"row_count": 10,
|
|
"columns": ["id", "pubkey", "created_at", "kind", "content", "tags", "sig"],
|
|
"rows": [
|
|
["abc123...", "def456...", 1234567890, 1, "Hello world", "[]", "sig123..."],
|
|
["ghi789...", "jkl012...", 1234567880, 0, "{\"name\":\"Alice\"}", "[]", "sig456..."]
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Security Features
|
|
|
|
- **Read-only**: Only SELECT statements allowed
|
|
- **Query timeout**: 5 seconds maximum
|
|
- **Result limit**: 1000 rows maximum
|
|
- **Logging**: All queries logged with execution time
|
|
- **Validation**: SQL injection protection
|
|
|
|
#### Available Tables and Views
|
|
|
|
**Core Tables**:
|
|
- `events` - All Nostr events
|
|
- `config` - Configuration parameters
|
|
- `auth_rules` - Authentication rules
|
|
- `subscription_events` - Subscription lifecycle log
|
|
- `event_broadcasts` - Event broadcast log
|
|
|
|
**Views**:
|
|
- `recent_events` - Last 1000 events
|
|
- `event_stats` - Event statistics by type
|
|
- `subscription_analytics` - Subscription metrics
|
|
- `active_subscriptions_log` - Currently active subscriptions
|
|
- `event_kinds_view` - Event distribution by kind
|
|
- `top_pubkeys_view` - Top 10 pubkeys by event count
|
|
- `time_stats_view` - Time-based statistics
|
|
|
|
#### Example Queries
|
|
|
|
**Recent events**:
|
|
```sql
|
|
SELECT id, pubkey, created_at, kind
|
|
FROM events
|
|
ORDER BY created_at DESC
|
|
LIMIT 20
|
|
```
|
|
|
|
**Event distribution**:
|
|
```sql
|
|
SELECT * FROM event_kinds_view
|
|
ORDER BY count DESC
|
|
```
|
|
|
|
**Active subscriptions**:
|
|
```sql
|
|
SELECT * FROM active_subscriptions_log
|
|
ORDER BY created_at DESC
|
|
```
|
|
|
|
**Database statistics**:
|
|
```sql
|
|
SELECT
|
|
(SELECT COUNT(*) FROM events) as total_events,
|
|
(SELECT COUNT(*) FROM subscription_events) as total_subscriptions,
|
|
(SELECT COUNT(DISTINCT pubkey) FROM events) as unique_pubkeys
|
|
```
|
|
|
|
**Events by specific pubkey**:
|
|
```sql
|
|
SELECT id, created_at, kind, content
|
|
FROM events
|
|
WHERE pubkey = 'abc123...'
|
|
ORDER BY created_at DESC
|
|
LIMIT 50
|
|
```
|
|
|
|
**Events in time range**:
|
|
```sql
|
|
SELECT COUNT(*) as count, kind
|
|
FROM events
|
|
WHERE created_at BETWEEN 1234567000 AND 1234567890
|
|
GROUP BY kind
|
|
ORDER BY count DESC
|
|
```
|
|
|
|
## Configuration Reference
|
|
|
|
### Basic Relay Settings
|
|
|
|
| Key | Type | Default | Description |
|
|
|-----|------|---------|-------------|
|
|
| `relay_name` | string | "C-Relay" | Relay name (NIP-11) |
|
|
| `relay_description` | string | "C Nostr Relay" | Relay description |
|
|
| `relay_contact` | string | "" | Admin contact info |
|
|
| `relay_software` | string | "c-relay" | Software identifier |
|
|
| `relay_version` | string | auto | Software version |
|
|
| `supported_nips` | string | "1,9,11,13,15,20,33,40,42,45,50,70" | Supported NIPs |
|
|
| `language_tags` | string | "*" | Supported languages |
|
|
| `relay_countries` | string | "*" | Supported countries |
|
|
| `posting_policy` | string | "" | Posting policy URL |
|
|
| `payments_url` | string | "" | Payment URL |
|
|
|
|
### Connection & Limits
|
|
|
|
| Key | Type | Default | Range | Restart Required |
|
|
|-----|------|---------|-------|------------------|
|
|
| `max_connections` | integer | 1000 | 1-10000 | Yes |
|
|
| `max_subscriptions_per_client` | integer | 25 | 1-100 | No |
|
|
| `max_total_subscriptions` | integer | 5000 | 100-50000 | No |
|
|
| `max_message_length` | integer | 65536 | 1024-1048576 | No |
|
|
| `max_event_tags` | integer | 2000 | 10-10000 | No |
|
|
| `max_content_length` | integer | 65536 | 1-1048576 | No |
|
|
|
|
### Authentication & Access Control
|
|
|
|
| Key | Type | Default | Description |
|
|
|-----|------|---------|-------------|
|
|
| `auth_enabled` | boolean | false | Enable whitelist/blacklist |
|
|
| `nip42_auth_required` | boolean | false | Require NIP-42 auth |
|
|
| `nip42_auth_required_kinds` | string | "" | Kinds requiring NIP-42 |
|
|
| `nip42_challenge_timeout` | integer | 300 | Challenge timeout (seconds) |
|
|
|
|
### Proof of Work (NIP-13)
|
|
|
|
| Key | Type | Default | Values | Description |
|
|
|-----|------|---------|--------|-------------|
|
|
| `pow_min_difficulty` | integer | 0 | 0-40 | Minimum PoW difficulty |
|
|
| `pow_mode` | string | "optional" | disabled/optional/required | PoW enforcement mode |
|
|
|
|
### Event Expiration (NIP-40)
|
|
|
|
| Key | Type | Default | Description |
|
|
|-----|------|---------|-------------|
|
|
| `nip40_expiration_enabled` | boolean | true | Enable expiration support |
|
|
| `nip40_expiration_strict` | boolean | false | Reject expired events |
|
|
| `nip40_expiration_filter` | boolean | true | Filter expired from results |
|
|
| `nip40_expiration_grace_period` | integer | 300 | Grace period (seconds) |
|
|
|
|
### Monitoring
|
|
|
|
| Key | Type | Default | Description |
|
|
|-----|------|---------|-------------|
|
|
| `kind_24567_reporting_throttle_sec` | integer | 5 | Monitoring event throttle |
|
|
|
|
### Dynamic vs Restart-Required
|
|
|
|
**Dynamic (No Restart)**:
|
|
- All NIP-11 relay information
|
|
- Authentication settings
|
|
- Subscription limits
|
|
- Event validation limits
|
|
- Proof of Work settings
|
|
- Expiration settings
|
|
|
|
**Restart Required**:
|
|
- `max_connections`
|
|
- `relay_port`
|
|
- Database settings
|
|
|
|
## Real-time Monitoring
|
|
|
|
C-Relay provides subscription-based real-time monitoring using ephemeral events (kind 24567).
|
|
|
|
### Activation
|
|
|
|
Subscribe to kind 24567 events to activate monitoring:
|
|
|
|
```json
|
|
["REQ", "monitoring-sub", {"kinds": [24567]}]
|
|
```
|
|
|
|
### Monitoring Event Types
|
|
|
|
Subscribe to specific monitoring types using d-tag filters:
|
|
|
|
```json
|
|
["REQ", "event-kinds", {"kinds": [24567], "#d": ["event_kinds"]}]
|
|
["REQ", "time-stats", {"kinds": [24567], "#d": ["time_stats"]}]
|
|
["REQ", "top-pubkeys", {"kinds": [24567], "#d": ["top_pubkeys"]}]
|
|
["REQ", "cpu-metrics", {"kinds": [24567], "#d": ["cpu_metrics"]}]
|
|
```
|
|
|
|
### Event Structure
|
|
|
|
```json
|
|
{
|
|
"kind": 24567,
|
|
"pubkey": "relay_pubkey",
|
|
"created_at": 1234567890,
|
|
"content": "{\"data_type\":\"event_kinds\",\"timestamp\":1234567890,...}",
|
|
"tags": [
|
|
["d", "event_kinds"]
|
|
]
|
|
}
|
|
```
|
|
|
|
### Monitoring Types
|
|
|
|
#### Event Distribution (`event_kinds`)
|
|
|
|
```json
|
|
{
|
|
"data_type": "event_kinds",
|
|
"timestamp": 1234567890,
|
|
"total_events": 15432,
|
|
"kinds": [
|
|
{"kind": 1, "count": 12000, "percentage": 77.8},
|
|
{"kind": 0, "count": 2500, "percentage": 16.2}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Time Statistics (`time_stats`)
|
|
|
|
```json
|
|
{
|
|
"data_type": "time_stats",
|
|
"timestamp": 1234567890,
|
|
"total_events": 15432,
|
|
"last_24h": 234,
|
|
"last_7d": 1456,
|
|
"last_30d": 5432
|
|
}
|
|
```
|
|
|
|
#### Top Publishers (`top_pubkeys`)
|
|
|
|
```json
|
|
{
|
|
"data_type": "top_pubkeys",
|
|
"timestamp": 1234567890,
|
|
"top_pubkeys": [
|
|
{"pubkey": "abc123...", "count": 1234, "percentage": 8.0},
|
|
{"pubkey": "def456...", "count": 987, "percentage": 6.4}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### CPU Metrics (`cpu_metrics`)
|
|
|
|
```json
|
|
{
|
|
"data_type": "cpu_metrics",
|
|
"timestamp": 1234567890,
|
|
"cpu_percent": 12.5,
|
|
"memory_mb": 45.2,
|
|
"uptime_seconds": 86400
|
|
}
|
|
```
|
|
|
|
#### Active Subscriptions (`active_subscriptions`) - Admin Only
|
|
|
|
```json
|
|
{
|
|
"data_type": "active_subscriptions",
|
|
"timestamp": 1234567890,
|
|
"total_subscriptions": 156,
|
|
"subscriptions_by_client": [
|
|
{"client_id": "client1", "count": 12},
|
|
{"client_id": "client2", "count": 8}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Configuration
|
|
|
|
Control monitoring frequency:
|
|
|
|
```json
|
|
["config_update", [{
|
|
"key": "kind_24567_reporting_throttle_sec",
|
|
"value": "10",
|
|
"data_type": "integer",
|
|
"category": "monitoring"
|
|
}]]
|
|
```
|
|
|
|
### Performance
|
|
|
|
- Events are ephemeral (not stored)
|
|
- Automatic activation/deactivation based on subscriptions
|
|
- Throttling prevents excessive event generation
|
|
- Minimal overhead when no clients monitoring
|
|
|
|
## Direct Message Admin
|
|
|
|
Control your relay by sending direct messages from any Nostr client.
|
|
|
|
### Setup
|
|
|
|
1. The relay has its own keypair (shown on startup)
|
|
2. The relay knows the admin public key
|
|
3. Send NIP-17 direct messages to the relay
|
|
|
|
### Available Commands
|
|
|
|
Send a DM containing any of these keywords:
|
|
|
|
| Command | Aliases | Response |
|
|
|---------|---------|----------|
|
|
| Statistics | stats, statistics | Database statistics |
|
|
| Configuration | config, configuration | Current configuration |
|
|
|
|
### Example
|
|
|
|
Using any Nostr client that supports NIP-17:
|
|
|
|
1. Find the relay's public key (shown on startup)
|
|
2. Send a DM: "stats"
|
|
3. Receive a DM with current relay statistics
|
|
|
|
### Response Format
|
|
|
|
The relay responds with a NIP-17 DM containing:
|
|
|
|
**Stats Response**:
|
|
```
|
|
Relay Statistics
|
|
================
|
|
Total Events: 15,432
|
|
Database Size: 10.5 MB
|
|
Active Connections: 42
|
|
Active Subscriptions: 156
|
|
Uptime: 1 day, 2 hours
|
|
```
|
|
|
|
**Config Response**:
|
|
```
|
|
Relay Configuration
|
|
===================
|
|
Name: My Awesome Relay
|
|
Description: Community relay
|
|
Max Subscriptions: 25
|
|
Auth Enabled: false
|
|
PoW Difficulty: 0
|
|
```
|
|
|
|
## Response Formats
|
|
|
|
### Success Response
|
|
|
|
```json
|
|
{
|
|
"query_type": "command_name",
|
|
"status": "success",
|
|
"message": "Operation completed successfully",
|
|
"timestamp": 1234567890,
|
|
"data": [...]
|
|
}
|
|
```
|
|
|
|
### Error Response
|
|
|
|
```json
|
|
{
|
|
"query_type": "command_name",
|
|
"status": "error",
|
|
"error": "Error description",
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
### Query Response
|
|
|
|
```json
|
|
{
|
|
"query_type": "query_name",
|
|
"total_results": 10,
|
|
"timestamp": 1234567890,
|
|
"data": [...]
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### Common Errors
|
|
|
|
| Error | Cause | Solution |
|
|
|-------|-------|----------|
|
|
| `invalid_signature` | Event signature invalid | Check admin private key |
|
|
| `unauthorized` | Wrong admin pubkey | Use correct admin key |
|
|
| `invalid_command` | Unknown command | Check command format |
|
|
| `validation_failed` | Invalid parameter value | Check parameter ranges |
|
|
| `database_error` | Database operation failed | Check database integrity |
|
|
| `timeout` | Query took too long | Simplify query or increase timeout |
|
|
|
|
### Error Response Example
|
|
|
|
```json
|
|
{
|
|
"query_type": "config_update",
|
|
"status": "error",
|
|
"error": "field validation failed: invalid port number '99999' (must be 1-65535)",
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
## Examples
|
|
|
|
### JavaScript/TypeScript Example
|
|
|
|
```javascript
|
|
import { SimplePool, nip44, getPublicKey, finalizeEvent } from 'nostr-tools';
|
|
|
|
const adminPrivkey = 'your_admin_privkey_hex';
|
|
const adminPubkey = getPublicKey(adminPrivkey);
|
|
const relayPubkey = 'relay_pubkey_hex';
|
|
const relayUrl = 'ws://localhost:8888';
|
|
|
|
// Create admin command
|
|
async function sendAdminCommand(command) {
|
|
const pool = new SimplePool();
|
|
|
|
// Encrypt command with NIP-44
|
|
const encryptedContent = await nip44.encrypt(
|
|
adminPrivkey,
|
|
relayPubkey,
|
|
JSON.stringify(command)
|
|
);
|
|
|
|
// Create event
|
|
const event = finalizeEvent({
|
|
kind: 23456,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags: [['p', relayPubkey]],
|
|
content: encryptedContent
|
|
}, adminPrivkey);
|
|
|
|
// Publish event
|
|
await pool.publish([relayUrl], event);
|
|
|
|
// Subscribe to response
|
|
const sub = pool.sub([relayUrl], [{
|
|
kinds: [23457],
|
|
'#p': [adminPubkey],
|
|
since: Math.floor(Date.now() / 1000)
|
|
}]);
|
|
|
|
return new Promise((resolve) => {
|
|
sub.on('event', async (event) => {
|
|
// Decrypt response
|
|
const decrypted = await nip44.decrypt(
|
|
adminPrivkey,
|
|
relayPubkey,
|
|
event.content
|
|
);
|
|
resolve(JSON.parse(decrypted));
|
|
sub.unsub();
|
|
});
|
|
});
|
|
}
|
|
|
|
// Query configuration
|
|
const config = await sendAdminCommand(['config_query', 'all']);
|
|
console.log(config);
|
|
|
|
// Update configuration
|
|
const result = await sendAdminCommand(['config_update', [
|
|
{
|
|
key: 'relay_name',
|
|
value: 'My Relay',
|
|
data_type: 'string',
|
|
category: 'relay'
|
|
}
|
|
]]);
|
|
console.log(result);
|
|
|
|
// Add blacklist rule
|
|
const blacklist = await sendAdminCommand([
|
|
'blacklist',
|
|
'pubkey',
|
|
'abc123...'
|
|
]);
|
|
console.log(blacklist);
|
|
|
|
// Execute SQL query
|
|
const query = await sendAdminCommand([
|
|
'sql_query',
|
|
'SELECT * FROM events ORDER BY created_at DESC LIMIT 10'
|
|
]);
|
|
console.log(query);
|
|
```
|
|
|
|
### Python Example
|
|
|
|
```python
|
|
from nostr_sdk import Keys, Client, EventBuilder, Filter, nip44
|
|
|
|
admin_privkey = "your_admin_privkey_hex"
|
|
relay_pubkey = "relay_pubkey_hex"
|
|
relay_url = "ws://localhost:8888"
|
|
|
|
# Initialize
|
|
keys = Keys.parse(admin_privkey)
|
|
client = Client(keys)
|
|
client.add_relay(relay_url)
|
|
client.connect()
|
|
|
|
# Send admin command
|
|
async def send_admin_command(command):
|
|
# Encrypt command
|
|
encrypted = nip44.encrypt(
|
|
keys.secret_key(),
|
|
relay_pubkey,
|
|
json.dumps(command)
|
|
)
|
|
|
|
# Create event
|
|
event = EventBuilder.new(
|
|
kind=23456,
|
|
content=encrypted,
|
|
tags=[["p", relay_pubkey]]
|
|
).to_event(keys)
|
|
|
|
# Publish
|
|
await client.send_event(event)
|
|
|
|
# Wait for response
|
|
filter = Filter().kind(23457).pubkey(relay_pubkey).since(int(time.time()))
|
|
events = await client.get_events_of([filter], timeout=5)
|
|
|
|
if events:
|
|
# Decrypt response
|
|
decrypted = nip44.decrypt(
|
|
keys.secret_key(),
|
|
relay_pubkey,
|
|
events[0].content()
|
|
)
|
|
return json.loads(decrypted)
|
|
|
|
# Query configuration
|
|
config = await send_admin_command(["config_query", "all"])
|
|
print(config)
|
|
```
|
|
|
|
### Bash/curl Example
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Note: This is a simplified example. Real implementation requires:
|
|
# - NIP-44 encryption
|
|
# - Event signing
|
|
# - WebSocket connection
|
|
|
|
RELAY_URL="ws://localhost:8888"
|
|
ADMIN_PRIVKEY="your_admin_privkey"
|
|
RELAY_PUBKEY="relay_pubkey"
|
|
|
|
# Use nostrtool or similar for proper event creation
|
|
nostrtool event \
|
|
--kind 23456 \
|
|
--content "$(echo '["config_query","all"]' | nip44-encrypt)" \
|
|
--tag p "$RELAY_PUBKEY" \
|
|
--private-key "$ADMIN_PRIVKEY" \
|
|
| nostrtool send "$RELAY_URL"
|
|
```
|
|
|
|
---
|
|
|
|
## Additional Resources
|
|
|
|
- **[Configuration Guide](docs/configuration_guide.md)** - Detailed configuration options
|
|
- **[Deployment Guide](docs/deployment_guide.md)** - Production deployment
|
|
- **[NIP-42 Authentication](docs/NIP-42_Authentication.md)** - Authentication setup
|
|
- **[User Guide](docs/user_guide.md)** - End-user documentation
|
|
|
|
## Support
|
|
|
|
For API questions or issues:
|
|
- Open an issue on GitHub
|
|
- Check existing documentation
|
|
- Join the Nostr community
|
|
|
|
---
|
|
|
|
**API Version**: 0.6.0
|
|
**Last Updated**: 2026-01-23
|