How to Integrate BitChat with Other Applications: Developer Guide for Nostr-Based Messaging

Yes, you can integrate BitChat with any application that supports Swift frameworks or speaks the Nostr protocol, using either direct API calls or the iOS Share Extension.

BitChat is a decentralized messenger built on the Nostr protocol, which means it uses a public, JSON-based WebSocket API rather than proprietary servers. This architecture makes integration straightforward for developers who want to embed privacy-focused messaging into their own apps. The core integration paths are defined in the permissionlesstech/bitchat repository, specifically within the bitchat/Nostr/ directory.

Two Methods to Integrate BitChat with Your Application

BitChat offers two distinct integration approaches depending on your technical requirements and platform constraints.

Nostr Client API: Direct Programmatic Integration

The Nostr client API lets your application send, receive, and subscribe to Nostr events programmatically. This method gives you full control over message flow, filtering, and relay selection.

The central component is NostrRelayManager.swift, which handles all WebSocket connections, exponential back-off reconnection, message queueing, and event deduplication. You interact with this manager through its public methods rather than managing raw WebSocket connections yourself.

Key components:

iOS Share Extension: Zero-Code Integration for Any iOS App

The Share Extension allows any iOS application to forward content into BitChat conversations without implementing Nostr code. When a user selects BitChat from the standard iOS share sheet, ShareViewController.swift receives the payload, constructs a NostrEvent, and dispatches it through the same NostrRelayManager pipeline used internally.

This requires no code changes in the host application — only the standard UIActivityViewController invocation.

Why BitChat Integration Works Out-of-the-Box

Four architectural decisions in the BitChat codebase make third-party integration reliable and predictable:

  1. Protocol-agnostic design — All network traffic flows through the pure Nostr layer. There is no proprietary BitChat server; any reachable Nostr relay suffices.

  2. Configurable relay list — The app ships with four default public relays, but NostrRelaySettings.add(_:builtIn:) supports up to eight custom relays including .onion addresses. This enables corporate or privacy-focused deployments.

  3. Tor support — When enabled via TorManager.shared, NostrRelayManager automatically routes WebSocket traffic through TorURLSession.shared.session, supporting anonymous messaging integrations.

  4. Resilient message delivery — The manager queues outbound events when relays are offline (messageQueue), applies exponential back-off (initialBackoffInterval, maxBackoffInterval), and retries transparently. Your code can fire-and-forget events.

Code Examples for BitChat Integration

Sending a Chat Message from Your Swift App

import BitChat
import Foundation

// Create a Nostr event with library helpers for signing
let messageText = "Hello from my app!"
let event = NostrEvent(kind: .textNote, content: messageText, tags: [])

// Send to all configured relays via the shared manager
NostrRelayManager.shared.sendEvent(event)

// Or wait for relay acknowledgment with the confirmed send API
NostrRelayManager.shared.sendEventImmediately(event) { accepted in
    print(accepted ? "✅ Delivered" : "❌ Failed")
}

Source reference: NostrRelayManager.sendEvent(_:) and sendEventImmediately(_:completion:) handle serialization, signing, and delivery across all active connections.

Subscribing to Incoming Messages

let filter = NostrFilter(kinds: [.textNote], limit: 100)

NostrRelayManager.shared.subscribe(
    filter: filter,
    handler: { event in
        // Process incoming chat message
        print("🔔 New message: \(event.content)")
    },
    onEOSE: {
        // End of stored events signal
        print("✅ Finished loading recent messages")
    })

Source reference: NostrRelayManager.subscribe(filter:id:relayUrls:handler:onEOSE:) in NostrRelayManager.swift manages subscription state across multiple relays.

Adding a Custom Relay for Private Deployments

let customRelay = "wss://my-private-relay.onion"
let result = NostrRelaySettings.add(customRelay,
                                    builtIn: NostrRelayManager.builtInRelayURLs)

switch result {
case .success(let normalized):
    print("✅ Added relay: \(normalized)")
case .failure(let err):
    print("❌ Could not add relay: \(err)")
}

Source reference: NostrRelaySettings.add(_:builtIn:in:) normalizes URLs, validates reachability, and enforces the eight-relay limit.

Invoking BitChat from Another iOS App

// Standard iOS share sheet — no BitChat-specific code required
let text = "Check out this photo!"
let activityVC = UIActivityViewController(
    activityItems: [text],
    applicationActivities: nil
)
present(activityVC, animated: true)

The user selects BitChat from the share sheet. ShareViewController.swift automatically converts the payload to a NostrEvent and enqueues it via NostrRelayManager.shared.sendEvent(event).

Key Source Files for Integration Development

File Path Responsibility
NostrRelayManager.swift bitchat/Nostr/NostrRelayManager.swift WebSocket relay management, queuing, reconnection, deduplication
NostrRelaySettings.swift bitchat/Nostr/NostrRelaySettings.swift Relay URL persistence, validation, normalization
NostrProtocol.swift bitchat/Nostr/NostrProtocol.swift Event and filter type definitions
NostrRelayURL.swift bitchat/Nostr/NostrRelayURL.swift URL parsing and Tor detection
ShareViewController.swift bitchatShareExtension/ShareViewController.swift iOS Share Extension entry point
Info.plist bitchatShareExtension/Info.plist Extension capabilities and entitlements

Summary

  • BitChat integrates with other applications through two mechanisms: direct Nostr API calls via NostrRelayManager or the iOS Share Extension for zero-code sharing.
  • NostrRelayManager.swift provides the complete interface: sendEvent(_:), sendEventImmediately(_:completion:), and subscribe(filter:id:relayUrls:handler:onEOSE:).
  • Custom relays enable private or corporate deployments through NostrRelaySettings.add(_:builtIn:).
  • Tor routing is automatically handled when TorManager is active, requiring no additional integration code.
  • Message delivery guarantees include queuing, exponential back-off, and deduplication — your application can fire-and-forget events.

Frequently Asked Questions

Can I integrate BitChat with Android or web applications?

BitChat's core Nostr implementation is Swift-based for iOS, but any platform that speaks Nostr can interoperate. Web and Android applications can connect to the same relays using Nostr libraries in JavaScript (like nostr-tools) or Kotlin. The protocol is identical; only the NostrRelayManager wrapper is iOS-specific.

Do I need to run my own relay to integrate BitChat?

No. BitChat works with any public Nostr relay. However, running a private relay (added via NostrRelaySettings.add) gives you control over message routing, retention policies, and network access — useful for enterprise integrations.

How does the Share Extension handle different content types?

ShareViewController.swift inspects the NSExtensionItem attachments and builds appropriate NostrEvent objects. Text becomes kind: .textNote events; images and files are handled according to Nostr's media conventions. The same NostrRelayManager.sendEvent(_:) pipeline delivers all content types.

Is message delivery guaranteed when relays are offline?

Yes, via client-side queuing. NostrRelayManager maintains a messageQueue and applies exponential back-off (initialBackoffInterval, maxBackoffInterval) to retry delivery. Events are deduplicated by ID across reconnections, ensuring exactly-once delivery semantics without duplicate messages.

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 →