Bitchat API Endpoints: Understanding the Nostr Relay Architecture

Bitchat does not expose traditional REST API endpoints—instead, it communicates through WebSocket connections to Nostr relay servers.

Bitchat is a Swift-based messaging application built on the Nostr protocol, a decentralized social network layer. Rather than hosting its own API, the app connects to public and user-configured relay servers that act as message hubs. This article explains how Bitchat API endpoints work as implemented in the permissionlesstech/bitchat repository.

How Bitchat Connects to Relays

All network communication in Bitchat flows through NostrRelayManager.swift. This core component manages WebSocket connections to relay servers, handles message queuing, and provides a Swift-native interface for the NIP-01 protocol.

Default Bitchat API Endpoints (Built-in Relays)

When initialized, the manager automatically connects to two hard-coded relays:

Relay Name WebSocket URL Purpose
Damus wss://relay.damus.io General purpose public relay
Primal wss://relay.primal.net High-availability message routing

These URLs represent the default API endpoints that Bitchat uses out of the box. The built-in array is defined at line 157 in NostrRelayManager.swift.

User-Configurable Relays

The app allows users to add custom relay URLs through the settings interface. NostrRelaySettings.swift handles:

  • URL normalization and validation
  • Persistence via UserDefaults
  • Support for .onion Tor addresses

Custom relays are merged with the defaults and treated identically as Bitchat API endpoints.

Core Methods in NostrRelayManager

Sending Events to Relays

Publish a Nostr event to all connected relays:

let manager = NostrRelayManager(/* dependencies */)
let event = NostrEvent(kind: 1, content: "Hello, Nostr!", tags: [])

// Broadcasts to damus.io, primal.net, and any user-added relays
await manager.sendEvent(event)

Targeting Specific Relays

Send to a curated subset of endpoints:

let customRelays = ["wss://relay.example.com", "wss://nostr.wine"]
await manager.sendEvent(event, to: customRelays)

Managing Connections

Explicitly ensure connections before operations:

let targetUrls = [
    "wss://relay.damus.io",
    "wss://relay.primal.net"
]
await manager.ensureConnections(to: targetUrls)

Subscribing to Feeds

Request real-time updates matching a filter:

let filter = NostrFilter(
    kinds: [1],      // Text notes
    authors: nil,    // Any author
    tags: nil        // No tag filtering
)
await manager.subscribe(to: filter)

The Nostr Protocol: Message Types

All communication over Bitchat's API endpoints follows NIP-01 specifications. The NostrProtocol.swift file defines the JSON message envelope:

Message Direction Purpose
EVENT Client → Relay Publish a signed event
REQ Client → Relay Subscribe to matching events
EOSE Relay → Client End of stored events marker
OK Relay → Client Acknowledgment of published event

These are not HTTP endpoints—each message is a JSON frame sent over a persistent WebSocket connection.

Key Source Files

Understanding these three files clarifies Bitchat's entire API surface:

File Responsibility
bitchat/Nostr/NostrRelayManager.swift WebSocket lifecycle, connection pooling, event queuing
bitchat/Nostr/NostrRelaySettings.swift User relay preferences, URL validation, persistent storage
bitchat/Nostr/NostrProtocol.swift Message serialization, NIP-01 compliance

Summary

  • Bitchat has no REST API—it uses WebSocket-based Nostr relays as distributed endpoints.
  • Default endpoints are wss://relay.damus.io and wss://relay.primal.net, hard-coded in NostrRelayManager.swift.
  • Custom relays can be added via settings and are persisted through NostrRelaySettings.swift.
  • Swift methods like sendEvent(_:), ensureConnections(to:), and subscribe(to:) abstract the NIP-01 protocol.

Frequently Asked Questions

Does Bitchat have a REST API for integrations?

No. Bitchat does not expose HTTP endpoints. All functionality is implemented through Nostr's WebSocket protocol to relay servers. External integrations would need to speak Nostr directly rather than calling a Bitchat-hosted API.

Can I change which relays Bitchat connects to?

Yes. The app supports adding custom relay URLs through its settings interface. These are stored in UserDefaults and loaded alongside the default Damus and Primal relays on startup. Tor .onion addresses are explicitly supported.

What protocol do Bitchat's API endpoints use?

All endpoints use WebSockets with the NIP-01 Nostr protocol. Messages are JSON objects—not HTTP requests. This is implemented across NostrRelayManager.swift (connection handling), NostrRelaySettings.swift (configuration), and NostrProtocol.swift (message formatting).

Where are the relay URLs defined in the source code?

The default relay array appears at line 157 of NostrRelayManager.swift in the main repository. User-added relays are managed separately in NostrRelaySettings.swift.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →