Swarm API Reference
Public Endpoints
GET /api/swarm/users/[handle]
Returns a user’s profile and recent posts. Used by other nodes to display remote user profiles.
Query Parameters:
limit(number, default: 25, max: 50) - Max posts to return
Response:
{
"profile": {
"handle": "alice",
"displayName": "Alice",
"bio": "Building cool stuff",
"avatarUrl": "https://cdn.example.com/avatar.jpg",
"headerUrl": "https://cdn.example.com/header.jpg",
"website": "https://alice.dev",
"followersCount": 150,
"followingCount": 75,
"postsCount": 342,
"createdAt": "2024-01-15T12:00:00Z",
"isBot": false,
"nodeDomain": "example.synapsis.social"
},
"posts": [
{
"id": "abc123",
"content": "Hello world!",
"createdAt": "2024-01-20T15:30:00Z",
"isNsfw": false,
"likesCount": 12,
"repostsCount": 3,
"repliesCount": 5,
"media": [
{
"url": "https://cdn.example.com/image.jpg",
"mimeType": "image/jpeg",
"altText": "A photo"
}
],
"linkPreviewUrl": "https://example.com/article",
"linkPreviewTitle": "Article Title",
"linkPreviewDescription": "Article description",
"linkPreviewImage": "https://example.com/og-image.jpg"
}
],
"nodeDomain": "example.synapsis.social",
"timestamp": "2024-01-20T16:00:00Z"
}GET /api/swarm/timeline
Returns recent public posts from this node for the swarm-wide timeline.
Query Parameters:
limit(number, default: 20, max: 50) - Max posts to return
Response:
{
"posts": [
{
"id": "abc123",
"content": "Hello from this node!",
"createdAt": "2024-01-20T15:30:00Z",
"author": {
"handle": "alice",
"displayName": "Alice",
"avatarUrl": "https://...",
"isNsfw": false
},
"nodeDomain": "example.synapsis.social",
"nodeIsNsfw": false,
"isNsfw": false,
"likeCount": 12,
"repostCount": 3,
"replyCount": 5,
"media": [],
"linkPreviewUrl": null
}
],
"nodeDomain": "example.synapsis.social",
"nodeIsNsfw": false,
"timestamp": "2024-01-20T16:00:00Z"
}GET /.well-known/synapsis-swarm
Returns this node’s swarm information and known nodes.
Query Parameters:
nodes(boolean, default: true) - Include list of known nodeslimit(number, default: 50, max: 200) - Max nodes to return
Response:
{
"node": {
"domain": "example.synapsis.social",
"name": "Example Node",
"description": "A Synapsis node",
"publicKey": "-----BEGIN PUBLIC KEY-----...",
"softwareVersion": "0.1.0",
"capabilities": ["handles", "gossip"]
},
"swarm": {
"totalNodes": 42,
"activeNodes": 38,
"totalUsers": 1250,
"totalPosts": 15000,
"seeds": ["node.synapsis.social"]
},
"nodes": [
{
"domain": "other.synapsis.social",
"name": "Other Node",
"lastSeenAt": "2024-01-15T12:00:00Z"
}
]
}GET /api/swarm/info
Returns this node’s swarm information.
Query Parameters:
stats(boolean) - Include swarm statistics
Response:
{
"domain": "example.synapsis.social",
"name": "Example Node",
"description": "A Synapsis node",
"publicKey": "-----BEGIN PUBLIC KEY-----...",
"softwareVersion": "0.1.0",
"userCount": 150,
"postCount": 2500,
"capabilities": ["handles", "gossip"]
}GET /api/swarm/nodes
Returns list of known swarm nodes.
Query Parameters:
limit(number, default: 100, max: 500) - Max nodes to returnstats(boolean) - Include swarm statistics
Response:
{
"nodes": [
{
"domain": "node1.synapsis.social",
"name": "Node One",
"userCount": 100,
"postCount": 1500,
"lastSeenAt": "2024-01-15T12:00:00Z"
}
],
"stats": {
"totalNodes": 42,
"activeNodes": 38,
"totalUsers": 1250,
"totalPosts": 15000
}
}POST /api/swarm/announce
Receive an announcement from another node.
Request Body:
{
"domain": "new-node.synapsis.social",
"name": "New Node",
"description": "A new Synapsis node",
"publicKey": "-----BEGIN PUBLIC KEY-----...",
"softwareVersion": "0.1.0",
"userCount": 10,
"postCount": 50,
"capabilities": ["handles", "gossip"],
"timestamp": "2024-01-15T12:00:00Z"
}Response: Returns this node’s info (same format as request).
POST /api/swarm/gossip
Exchange node and handle information with another node.
Request Body:
{
"sender": "other-node.synapsis.social",
"nodes": [
{
"domain": "node1.synapsis.social",
"name": "Node One",
"lastSeenAt": "2024-01-15T12:00:00Z"
}
],
"handles": [
{
"handle": "alice",
"did": "did:key:z6Mk...",
"nodeDomain": "node1.synapsis.social",
"updatedAt": "2024-01-15T12:00:00Z"
}
],
"timestamp": "2024-01-15T12:00:00Z",
"since": "2024-01-14T00:00:00Z"
}Response:
{
"nodes": [...],
"handles": [...],
"received": {
"nodes": 5,
"handles": 25
}
}Admin Endpoints
POST /api/swarm/nodes (Admin)
Trigger swarm operations. Requires admin authentication.
Actions:
Announce to Seeds
{ "action": "announce" }Announce to Specific Node
{ "action": "announce", "domain": "target-node.com" }Discover a Node
{ "action": "discover", "domain": "new-node.com" }Run Gossip Round
{ "action": "gossip" }Gossip with Specific Node
{ "action": "gossip", "domain": "target-node.com" }Add Seed Node
{ "action": "addSeed", "domain": "new-seed.com", "priority": 50 }Database Schema
swarm_nodes
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| domain | text | Node domain (unique) |
| name | text | Display name |
| description | text | Node description |
| logo_url | text | Logo URL |
| public_key | text | Node’s public key |
| software_version | text | Synapsis version |
| user_count | integer | Number of users |
| post_count | integer | Number of posts |
| discovered_via | text | How we found this node |
| discovered_at | timestamp | When discovered |
| last_seen_at | timestamp | Last successful contact |
| last_sync_at | timestamp | Last gossip sync |
| consecutive_failures | integer | Failed contact attempts |
| is_active | boolean | Currently reachable |
| trust_score | integer | Reputation (0-100) |
| capabilities | text | JSON array of capabilities |
swarm_seeds
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| domain | text | Seed domain (unique) |
| priority | integer | Connection order (lower = first) |
| is_enabled | boolean | Whether to use this seed |
| last_contact_at | timestamp | Last successful contact |
| consecutive_failures | integer | Failed contact attempts |
swarm_sync_log
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| remote_domain | text | Node we synced with |
| direction | text | ’push’ or ‘pull’ |
| nodes_received | integer | Nodes received |
| nodes_sent | integer | Nodes sent |
| handles_received | integer | Handles received |
| handles_sent | integer | Handles sent |
| success | boolean | Whether sync succeeded |
| error_message | text | Error if failed |
| duration_ms | integer | Sync duration |
Interaction Endpoints
These endpoints enable direct node-to-node social interactions with instant delivery.
GET /api/swarm/posts/[id]
Returns a single post with author info.
Response:
{
"id": "abc123",
"content": "Hello world!",
"createdAt": "2024-01-20T15:30:00Z",
"author": {
"handle": "alice",
"displayName": "Alice",
"avatarUrl": "https://...",
"isNsfw": false
},
"nodeDomain": "example.synapsis.social",
"isNsfw": false,
"likesCount": 12,
"repostsCount": 3,
"repliesCount": 5,
"media": [],
"linkPreviewUrl": null,
"replyToId": null,
"repostOfId": null
}POST /api/swarm/interactions/like
Receive a like from another swarm node.
Request Body:
{
"postId": "uuid-of-target-post",
"like": {
"actorHandle": "bob",
"actorDisplayName": "Bob",
"actorAvatarUrl": "https://other-node.com/avatar.jpg",
"actorNodeDomain": "other-node.com",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
},
"signature": "base64url-encoded-ecdsa-signature"
}Response:
{
"success": true,
"message": "Like received"
}POST /api/swarm/interactions/unlike
Receive an unlike from another swarm node.
Request Body:
{
"postId": "uuid-of-target-post",
"unlike": {
"actorHandle": "bob",
"actorNodeDomain": "other-node.com",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
},
"signature": "base64url-encoded-ecdsa-signature"
}Response:
{
"success": true,
"message": "Unlike received"
}POST /api/swarm/interactions/repost
Receive a repost notification from another swarm node.
Request Body:
{
"postId": "uuid-of-target-post",
"repost": {
"actorHandle": "bob",
"actorDisplayName": "Bob",
"actorAvatarUrl": "https://other-node.com/avatar.jpg",
"actorNodeDomain": "other-node.com",
"repostId": "uuid-of-repost-on-actors-node",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
},
"signature": "base64url-encoded-ecdsa-signature"
}Response:
{
"success": true,
"message": "Repost received"
}POST /api/swarm/interactions/follow
Receive a follow from another swarm node.
Request Body:
{
"targetHandle": "alice",
"follow": {
"followerHandle": "bob",
"followerDisplayName": "Bob",
"followerAvatarUrl": "https://other-node.com/avatar.jpg",
"followerBio": "Hello, I'm Bob",
"followerNodeDomain": "other-node.com",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
}
}Response:
{
"success": true,
"message": "Follow received"
}POST /api/swarm/interactions/unfollow
Receive an unfollow from another swarm node.
Request Body:
{
"targetHandle": "alice",
"unfollow": {
"followerHandle": "bob",
"followerNodeDomain": "other-node.com",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
}
}Response:
{
"success": true,
"message": "Unfollow received"
}POST /api/swarm/interactions/mention
Receive a mention notification from another swarm node.
Request Body:
{
"mentionedHandle": "alice",
"mention": {
"actorHandle": "bob",
"actorDisplayName": "Bob",
"actorAvatarUrl": "https://other-node.com/avatar.jpg",
"actorNodeDomain": "other-node.com",
"postId": "uuid-of-post-with-mention",
"postContent": "Hey @alice@this-node.com check this out!",
"interactionId": "unique-uuid",
"timestamp": "2024-01-20T15:30:00Z"
}
}Response:
{
"success": true,
"message": "Mention received"
}POST /api/swarm/replies
Receive a reply from another swarm node.
Request Body:
{
"postId": "uuid-of-parent-post",
"reply": {
"id": "uuid-of-reply-on-senders-node",
"content": "Great post!",
"createdAt": "2024-01-20T15:30:00Z",
"author": {
"handle": "bob",
"displayName": "Bob",
"avatarUrl": "https://other-node.com/avatar.jpg"
},
"nodeDomain": "other-node.com",
"mediaUrls": []
}
}Response:
{
"success": true,
"replyId": "uuid-of-created-reply"
}GET /api/swarm/replies
Get replies to a post on this node.
Query Parameters:
postId(required) - UUID of the post
Response:
{
"replies": [
{
"id": "reply-uuid",
"content": "Great post!",
"createdAt": "2024-01-20T15:30:00Z",
"author": {
"handle": "bob@other-node.com",
"displayName": "Bob",
"avatarUrl": "https://..."
},
"likesCount": 2,
"repostsCount": 0,
"repliesCount": 1
}
],
"nodeDomain": "this-node.com"
}