Skip to content

Moderation API

Handles server-level spam prevention, trust management, and federation control endpoints.

Authentication: All endpoints require admin authentication via JWT token. See API: Server Administration for authentication details.

Scope: Layer 1 (Server-level) moderation only. For group-level moderation (Layer 2), see Moderation Architecture. For device-level blocking (Layer 3), see client-side implementation.


Grant instant trust to a device, bypassing the progressive trust period.

POST /admin/v1/trust/verify
POST /admin/v1/trust/verify HTTP/1.1
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"reason": "Known community member"
}

Parameters:

  • device_address: Device to verify
  • reason: Verification reason (for audit log)
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"trust_tier": "Verified",
"rate_limit": 300,
"verified_at": 1759000000,
"verified_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com"
}

Response Fields:

  • device_address: The verified device
  • trust_tier: New trust tier (See Progressive Trust Rate Limiting for valid values.)
  • rate_limit: New rate limit (300 messages/hour)
  • verified_at: Timestamp of verification
  • verified_by: Admin device address who verified

Effect: Device immediately gets 300 messages/hour rate limit, bypassing the 24-hour progressive trust period.

{
"error": "DEVICE_NOT_FOUND",
"message": "Device not registered on this server",
"code": 4013
}
{
"error": "INSUFFICIENT_PERMISSIONS",
"message": "Admin does not have 'verify_devices' permission",
"code": 4011
}

Override rate limit for a specific device (temporary or permanent).

POST /admin/v1/trust/set-rate-limit
POST /admin/v1/trust/set-rate-limit HTTP/1.1
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"device_address": "c4b5a6978869504132e1f2d3c4b5a697@server.com",
"custom_rate_limit": 150,
"reason": "Partial trust - monitoring behavior",
"expires_at": 1759086400
}

Parameters:

  • device_address: Target device
  • custom_rate_limit: Messages per hour (0-1000)
  • reason: Explanation for custom limit
  • expires_at: Optional expiration timestamp (null = permanent)
{
"device_address": "c4b5a6978869504132e1f2d3c4b5a697@server.com",
"rate_limit": 150,
"custom_limit_set_at": 1759000000,
"custom_limit_expires_at": 1759086400,
"set_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com"
}
{
"error": "INVALID_CONFIG",
"message": "Rate limit must be between 0 and 1000",
"code": 4012
}

View devices that may need manual verification

GET /admin/v1/trust/pending
GET /admin/v1/trust/pending?min_messages=10&max_age_hours=24 HTTP/1.1
Authorization: Bearer {admin_token}

Query Parameters:

  • min_age_hours: Minimum account age (default: 0)
  • max_age_hours: Maximum account age (default: 24)
  • min_messages: Minimum message count (default: 10)
  • max_spam_reports: Maximum spam reports (default: 0)
{
"pending_devices": [
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"registered_at": 1759000000,
"age_hours": 2,
"current_tier": "New",
"current_rate_limit": 10,
"messages_sent": 15,
"messages_received": 8,
"spam_reports": 0,
"suggested_action": "verify"
},
{
"device_address": "c4b5a6978869504132e1f2d3c4b5a697@server.com",
"registered_at": 1758995000,
"age_hours": 8,
"current_tier": "Established",
"current_rate_limit": 60,
"messages_sent": 150,
"messages_received": 200,
"spam_reports": 2,
"suggested_action": "monitor"
}
],
"total_count": 2
}

Suggested Actions:

  • verify: Good candidate for instant verification
  • monitor: Watch for suspicious behavior
  • block: High spam reports, consider blocking

Verify multiple devices at once.

POST /admin/v1/trust/verify-bulk
POST /admin/v1/trust/verify-bulk HTTP/1.1
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"devices": [
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"reason": "Known community member"
},
{
"device_address": "c4b5a6978869504132e1f2d3c4b5a697@server.com",
"reason": "Verified identity"
}
]
}
{
"verified_count": 2,
"failed_count": 0,
"results": [
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"success": true,
"verified_at": 1759000000
},
{
"device_address": "c4b5a6978869504132e1f2d3c4b5a697@server.com",
"success": true,
"verified_at": 1759000000
}
]
}

Block federation with another server.

POST /admin/v1/federation/block
POST /admin/v1/federation/block HTTP/1.1
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"server_domain": "spam-factory.com",
"reason": "Excessive spam reports from users",
"expires_at": null
}

Parameters:

  • server_domain: Domain to block
  • reason: Block reason (for audit and transparency)
  • expires_at: Optional expiration timestamp (null = permanent)
{
"server_domain": "spam-factory.com",
"blocked_at": 1759000000,
"blocked_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com",
"reason": "Excessive spam reports from users",
"expires_at": null
}

Effect: All federation requests from this server are rejected with HTTP 403.

{
"error": "INVALID_ADDRESS",
"message": "Invalid server domain format",
"code": 4005
}

Remove server from federation blocklist.

DELETE /admin/v1/federation/block/{server_domain}
DELETE /admin/v1/federation/block/spam-factory.com HTTP/1.1
Authorization: Bearer admin_token
{
"server_domain": "spam-factory.com",
"unblocked_at": 1759000000,
"unblocked_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com"
}

View all blocked servers.

GET /admin/v1/federation/blocklist
GET /admin/v1/federation/blocklist HTTP/1.1
Authorization: Bearer {admin_token}
{
"blocked_servers": [
{
"domain": "spam-factory.com",
"blocked_at": 1759000000,
"reason": "Excessive spam",
"blocked_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com",
"expires_at": null
},
{
"domain": "abusive-server.net",
"blocked_at": 1758990000,
"reason": "Harassment complaints",
"blocked_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com",
"expires_at": 1759090000
}
],
"total_blocked": 2
}

View reputation metrics for a federated server.

GET /admin/v1/federation/reputation/{server_domain}
GET /admin/v1/federation/reputation/other-server.com HTTP/1.1
Authorization: Bearer {admin_token}
{
"server_domain": "other-server.com",
"reputation_score": 0.85,
"metrics": {
"messages_delivered": 10000,
"messages_rejected": 50,
"spam_reports_received": 5,
"uptime_percentage": 99.9,
"average_response_time_ms": 120,
"certificate_valid": true
},
"federation_status": "active",
"federated_blocklist_count": 2,
"first_contact": 1758000000,
"last_activity": 1759000000
}

Response Fields:

  • reputation_score: 0.0 - 1.0 (higher = better reputation)
  • federation_status: active, limited, blocked
  • federated_blocklist_count: How many other servers block them

Reputation Score Calculation:

score = 1.0 - (spam_ratio x 0.5) - (rejection_ratio x 0.3) - (blocklist_penalty x 0.05)

where:

  • spam_ratio = spam_reports / messaged_delivered
  • rejection_ratio = messages_rejected / messages_delivered
  • blocklist_penalty = federated_blocklist_count
{
"error": "SERVER_UNREACHABLE",
"message": "Server not found in federation records",
"code": 4007
}

Configure federation settings and automatic blocking rules.

PUT /admin/v1/federation/policy
PUT /admin/v1/federation/policy HTTP/1.1
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"allowlist_mode": false,
"allowlist": [],
"auto_block_threshold": 0.2,
"require_certificate_validation": true,
"publish_blocklist": true
}

Parameters:

  • allowlist_mode: If true, only federate with servers in the allowlist
  • allowlist: List of allowed server domains. Only used if allowlist_mode is true.
  • auto_block_threshold: Auto-block servers with reputation below this value (0.0 - 1.0)
  • require_certificate_validation: Require valid TLS certificates
  • publish_blocklist: Publicly publish blocklist at /.well-known/cryptid-blocklist
{
"policy_updated_at": 1759000000,
"updated_by": "a1b2c3d4e5f61728394a5b6c7d8e9f10@server.com",
"current_policy": {
"allowlist_mode": false,
"allowlist": [],
"auto_block_threshold": 0.2,
"require_certificate_validation": true,
"publish_blocklist": true
}
}

Get detailed information about a specific device.

GET /admin/v1/devices/{device_address}
GET /admin/v1/devices/f1e2d3c4b5a6978869504132e1f2d3c4@server.com HTTP/1.1
Authorization: Bearer {admin_token}
{
"device_address": "f1e2d3c4b5a6978869504132e1f2d3c4@server.com",
"registered_at": 1758950000,
"age_hours": 50,
"trust_tier": "Trusted",
"admin_verified": false,
"metrics": {
"messages_sent": 547,
"messages_received": 892,
"spam_reports": 0,
"spam_reports_by_device": 2,
"last_active": 1759000000
},
"rate_limiting": {
"current_limit": 300,
"messages_this_hour": 45,
"reset_at": 1759003600,
"custom_limit": null,
"custom_limit_expires_at": null
},
"federation": {
"domains_contacted": [
"other-server.com",
"friend-server.net"
],
"federated_messages_sent": 120,
"federated_messages_received": 85
}
}

Response Fields:

  • spam_reports: Reports received against this device
  • spam_reports_by_device: Reports this device submitted (for report bombing detection)
  • custom_limit: Admin-set custom rate limit (if any)
{
"error": "DEVICE_NOT_FOUND",
"message": "Device not registered on this server",
"code": 4013
}

User-facing endpoint for reporting spam messages. This contributes to device reputation.

POST /v1/spam/report
POST /v1/spam/report HTTP/1.1
Content-Type: application/json
Authorization: Bearer {user_token}
{
"message_id": "msg_550e8400e29b41d4a716446655440000",
"sender_address": "spammer@other-server.com",
"reason": "spam",
"details": "Crypto scam spam"
}

Parameters:

  • message_id: ID of spam message
  • sender_address: Device address of spammer
  • reason: Report category
  • details: Optional additional context
{
"report_id": "report_550e8400e29b41d4a716446655440000",
"reported_at": 1759000000,
"action_taken": "recorded"
}

Server Actions:

  • Increments spam report count for the sender’s device
  • If the sender’s spam reports >= spam_report_block_threshold, auto-block the sender
  • Updates the sender’s server reputation (if federated)
  • Records in audit log

Privacy: Report is aggregated anonymously. Spammer is not notified.


Devices earn rate limits over 24 hours:

Trust TierAgeRate LimitCan Override
New0-6 hours10 msg/hourAdmin verify
Established6-24 hours60 msg/hourAdmin verify
Trusted24+ hours300 msg/hourAdmin custom limit
VerifiedAdmin override300 msg/hourAlready verified
Blocked5+ spam reports0 msg/hourCannot unblock via API

To unblock a device: Delete from blocklist (requires manual server configuration change for safety).

Servers track reputation of federated peers:

Good reputation (0.7-1.0):

  • Low spam reports
  • High message delivery success
  • Fast response times
  • Valid TLS certificate

Poor reputation (0.0-0.3):

  • High spam reports
  • Many message rejections
  • Frequent downtime
  • Blocked by many servers

Auto-blocking: If auto_block_threshold is set (e.g., 0.2), servers with reputation below this are automatically blocked.

To prevent spam report abuse (malicious users mass-reporting legitimate devices):

Rate limits on reporting:

  • Users can report max 10 devices/hour
  • Users can report max 50 devices/day

Threshold for action:

  • Single report: No action
  • 3-4 reports: Warning flag
  • 5+ reports: Auto-block

Admin review:

  • Admins can view spam report details
  • Can manually unblock false positives
  • Can ban malicious reporters

When enabled, server only federates with explicitly allowed domains:

[federation]
allowlist_mode = true
allowlist = [
"trusted-server1.com",
"trusted-server2.com",
"friend-server.net"
]

Use cases:

  • Private community servers
  • High-security deployments
  • Testing environments

If publish_blocklist = true, server publishes blocklist at:

GET /.well-known/cryptid-blocklist
{
"server": "my-server.com",
"blocklist_version": "1.0",
"last_updated": 1759000000,
"blocked_servers": [
{
"domain": "spam-factory.com",
"reason_category": "spam",
"severity": "high",
"blocked_since": 1758000000
}
],
"signature": "ed25519_signature"
}

Privacy: Only domain names and categories published, never specific devices or message content.

Other servers can subscribe to this blocklist for collaborative spam prevention.

Moderation endpoints preserve privacy:

What’s tracked:

  • Device behavior (message counts, spam reports)
  • Server reputation (aggregate metrics)
  • Federation patterns (which domains)

What’s NOT tracked:

  • Message content (always encrypted)
  • Message senders (not visible to server)
  • Social relationships (no contact lists)
  • Individual spam message content

Spam reports are aggregated anonymously. The server knows “Device X has 5 spam reports” but not “Alice reported Bob’s message about Y.”