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

> Integrate BitChat with your apps using Swift or the Nostr protocol. Learn how to connect Nostr-based messaging via API calls or the iOS Share Extension. Permissionless Tech developer guide.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: how-to-guide
- Published: 2026-08-01

---

**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`](https://github.com/permissionlesstech/bitchat/blob/main/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:**
- [`NostrRelayManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelayManager.swift) — manages connections, reconnect logic, and message delivery guarantees
- [`NostrRelaySettings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelaySettings.swift) — stores and validates custom relay URLs
- [`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) — defines message types (`EVENT`, `REQ`, `EOSE`, `NOTICE`, `OK`, `CLOSED`)

### 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`](https://github.com/permissionlesstech/bitchat/blob/main/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

```swift
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

```swift
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`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelayManager.swift) manages subscription state across multiple relays.

### Adding a Custom Relay for Private Deployments

```swift
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

```swift
// 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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelayManager.swift) | [`bitchat/Nostr/NostrRelayManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrRelayManager.swift) | WebSocket relay management, queuing, reconnection, deduplication |
| [`NostrRelaySettings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelaySettings.swift) | [`bitchat/Nostr/NostrRelaySettings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrRelaySettings.swift) | Relay URL persistence, validation, normalization |
| [`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) | [`bitchat/Nostr/NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrProtocol.swift) | Event and filter type definitions |
| [`NostrRelayURL.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrRelayURL.swift) | [`bitchat/Nostr/NostrRelayURL.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrRelayURL.swift) | URL parsing and Tor detection |
| [`ShareViewController.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ShareViewController.swift) | [`bitchatShareExtension/ShareViewController.swift`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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.