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
.onionTor 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.ioandwss://relay.primal.net, hard-coded inNostrRelayManager.swift. - Custom relays can be added via settings and are persisted through
NostrRelaySettings.swift. - Swift methods like
sendEvent(_:),ensureConnections(to:), andsubscribe(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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →