Start here
Add the package, create a hub, and show the board your users post to.
What you need
- iOS 26 or macOS 26 or later.
- Xcode 26 and Swift 6.2.
- An API key from your dashboard.
1. Add the package
In Xcode, choose File > Add Package Dependencies and paste this URL.
https://github.com/Different-Productions/DifferentRequestsSDK
Or in Package.swift:
dependencies: [
.package(
url: "https://github.com/Different-Productions/DifferentRequestsSDK",
from: "0.14.0"
),
],2. Get your API key
Your API key isn't a secret. It ships inside your app, and anyone who installs your app can read it off their device. It identifies your app; it doesn't protect it.
3. Show the board
A DifferentRequestsHub holds the board while your app runs: loaded pages and unsent drafts. Make one in your App, not inside a view, and hand it to the screen. A view is rebuilt often, and a hub made inside one would lose the user's place each time.
import DifferentRequests
import SwiftUI
@main
struct MyApp: App {
private let requests = DifferentRequestsHub(
client: DifferentRequestsClient(appKey: "your-api-key", baseURL: .production),
appearance: .standard,
emptyBoard: .standard,
notificationPermission: .askedBySDK
)
var body: some Scene {
WindowGroup {
NavigationStack {
DifferentRequestsView(hub: requests)
}
}
}
}4. Sign your users in
Reading the board needs only your API key. Voting, asking, following and commenting need a signed-in user. Pass each user's ID from your app as externalID, so nobody signs up twice.
NavigationStack {
DifferentRequestsView(hub: requests)
}
.task {
do {
let signedIn = try await requests.client.createSession(
externalID: currentUser.id,
email: currentUser.email,
displayName: currentUser.name,
proof: nil
)
logger.info("DifferentRequests: signed in as \(signedIn.user.id)")
} catch {
logger.error("DifferentRequests: \(error.localizedDescription)")
}
}Skip sign-in and the board still shows, but nobody can ask for anything. requests.client.describeIntegration() tells you when this is the case.
Use an externalID nobody can guess: a UUID stored for each user, not an email address or a sequential number. The same externalID is always the same user, so votes survive a reinstall.
5. Sign each sign-in on your server (optional)
Your API key says which app is asking, not which user. Anyone who installs your app can read the API key and could sign in as any user whose externalID they guess. If your app has its own server, create a signing secret on your app's API keys page in the dashboard, and your server signs each sign-in instead.
On your server, sign the user's externalID and an expiry time with the secret, and give the app the result. Any language with HMAC-SHA256 can do it. Encode the signature as URL-safe base64: standard base64 with - for +, _ for /, and no = padding.
let expiresAt = Int(Date().addingTimeInterval(300).timeIntervalSince1970)
let signature = Data(
HMAC<SHA256>.authenticationCode(
for: Data("\(externalID)\n\(expiresAt)".utf8),
using: SymmetricKey(data: Data(signingSecret.utf8))
)
)
.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")Your server makes the signature. Your app only passes it along:
let signedIn = try await requests.client.createSession(
externalID: currentUser.id,
email: currentUser.email,
displayName: currentUser.name,
proof: DRIdentityProof(
signature: fromServer.signature,
expiresAt: Date(timeIntervalSince1970: TimeInterval(fromServer.expiresAt))
)
)A DRIdentityProof lasts as long as you say, up to an hour. Sign a fresh one when a user opens your app rather than storing one on the device.
6. Load the board early (optional)
Loading the board's first page takes a moment. If you know it's about to be opened, load it while the user is still on another screen, and it opens already filled in.
Button("Requests") {
showingRequests = true
}
.task {
await requests.readTheBoardBeforeItIsShown()
}