iOS SDK 1.3.0

Voqal iOS SDK 1.3.0

The voice-first, render-spec SDK — drop in the assistant, point it at your backend, and ship a themed voice + chat experience.

Looking for the legacy SDK docs?

Integration

  1. In Xcode, choose File → Add Package Dependencies…
  2. Enter the package URL: https://github.com/VoqalAI/voqal-ios and add the VoqalSDK library.
  3. Set the dependency rule to Up to Next Major from 1.3.0.
  4. Minimum deployment target: iOS 16. Add NSMicrophoneUsageDescription and NSFaceIDUsageDescription to your Info.plist (mic for voice, Face ID for high-risk confirmations).

Setup

Step 1: Provide credentials via a delegate

Conform to VocalButtonDelegate. The SDK reads the auth token live on every request, so always return a currently-valid token — refresh it before it expires.

ViewController.swiftswift
import VoqalSDK

extension ViewController: VocalButtonDelegate {
    // Your end-user's auth token for the MCP backend (kept fresh by your app).
    func getToken() -> String { authStore.currentToken }

    // Optional JSON: country, user id, etc. Drives region + personalization.
    func getMetaData() -> String? {
        #"{"country_code":"EGY","user_id":"285"}"#
    }

    // The view controller the assistant is presented from.
    func getViewController() -> UIViewController { self }
    func voqalButton(didUploadRecording result: String) {}   // recording lifecycle
    func voqalButton(didFailWith error: Error) {}
}

Step 2: Configure & register the SDK

Build a VoqalSDKConfiguration, set your API key and theme, then register it once at launch.

AppDelegate.swiftswift
import VoqalSDK

func application(_ application: UIApplication,
                didFinishLaunchingWithOptions launchOptions: [...]?) -> Bool {

    var config = VoqalSDKConfiguration(requestId: "prod-yourapp")
    config.apiKey = "pk_live_…"            // your Voqal API key (required)
    config.theme  = VoqalTheme(accent: "#2d5bff", accent2: "#5b8dff",
                               appearance: .auto)
    config.home   = VoqalHome(
        userName: "Nour",
        pinnedCTAs: ["What's my balance?", "Create a payment link"])

    VoqalSDKManager.shared.setup(configuration: config)
    // Optional but recommended: warm the engine in the background so the
    // assistant answers instantly the first time it opens. Pass any object
    // conforming to VocalButtonDelegate (see the next step).
    VoqalSDKManager.shared.prewarm(delegate: voqalDelegate)
    return true
}
requestId selects the environment by prefix: prod- → production, stg- → staging.

Presenting the assistant

Two ways to open it — use the built-in orb button, or present it yourself from any of your own buttons.

Voice interaction: the user holds the orb to talk and releases to send (press-and-hold), or taps the keyboard icon to type. Voice, transcription, widgets, and confirmations are all handled inside the sheet.

Option A — the Voqal orb button

ViewController.swiftswift
let voqal = VoqalButton()
voqal.delegate = self            // your VocalButtonDelegate
view.addSubview(voqal)           // tapping it opens the assistant

Option B — present from any button

ViewController.swiftswift
@objc func openAssistant() {
    VoqalSDKManager.shared.presentChat(
        from: self,           // any UIViewController
        delegate: self,       // your VocalButtonDelegate
        animated: true)
}

Complete example

Everything together — register the SDK at launch, present it from your own button, and supply credentials live.

VoqalIntegration.swiftswift
import UIKit
import VoqalSDK

// 1) Register the SDK once at launch.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    // Retained so prewarm's background task always has live credentials.
    let voqalDelegate = VoqalCredentialsDelegate()

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        var config = VoqalSDKConfiguration(requestId: "prod-yourapp")  // "prod-" / "stg-"
        config.apiKey = "pk_live_…"                                    // your Voqal API key
        config.theme  = VoqalTheme(accent: "#2d5bff", accent2: "#5b8dff",
                                   appearance: .auto)
        config.home   = VoqalHome(userName: "Nour",
                                  pinnedCTAs: ["What's my balance?", "Create a payment link"])

        VoqalSDKManager.shared.setup(configuration: config)
        VoqalSDKManager.shared.prewarm(delegate: voqalDelegate)   // warm the engine at launch

        #if DEBUG
        VoqalSDKManager.shared.addLogSink(VoqalConsoleLogSink())       // log every event/error
        #endif
        return true
    }
}

// 2) Open the assistant from any of your own buttons.
final class HomeViewController: UIViewController {
    let voqal = VoqalCredentialsDelegate()
    @objc func openAssistant() {
        VoqalSDKManager.shared.presentChat(from: self, delegate: voqal, animated: true)
    }
}

// 3) Supply credentials live — the SDK reads these on every request.
final class VoqalCredentialsDelegate: NSObject, VocalButtonDelegate {
    func getToken() -> String { TokenStore.shared.current }   // keep this token fresh
    func getMetaData() -> String? { #"{"country_code":"EGY","user_id":"285"}"# }
    func getViewController() -> UIViewController {
        UIApplication.shared.connectedScenes
            .compactMap { ($0 as? UIWindowScene)?.keyWindow?.rootViewController }
            .first ?? UIViewController()
    }
    func voqalButton(didUploadRecording result: String) {}   // recording lifecycle
    func voqalButton(didFailWith error: Error) {}
}

Theming

One VoqalTheme drives the whole experience. Surfaces, hairlines and text tiers are derived automatically so it looks native in light or dark.

Theme.swiftswift
config.theme = VoqalTheme(
    accent: "#2d5bff",        // your brand color (hex)
    accent2: "#5b8dff",       // optional gradient pair
    appearance: .auto,        // .light · .dark · .auto (follows the phone)
    fontName: nil,            // optional custom display font
    radius: 20)               // base corner radius for cards & the sheet

Presentation style

Choose how the assistant appears. The default .sheet slides up and is swipe-to-dismiss; .fullScreen takes the whole screen edge-to-edge and dismisses via the close button. This is a setup-time setting.

AppDelegate.swiftswift
config.presentationStyle = .fullScreen   // default: .sheet

Header branding

Replace the default "Voqal" title and mark with your own. Set the header title on config.strings and the icon on config.icons. Leave them unset to fall back to the default Voqal title and mark.

AppDelegate.swiftswift
config.strings.chatHeaderTitle = "Rabbit"
config.icons.chatHeaderIcon = UIImage(named: "RabbitLogo")

Customization

  • Home screenVoqalHome(userName:pinnedCTAs:showAgentGlance:): the greeting name, the "Try saying" suggestions, and whether to show the live data glance.
  • Presentationconfig.presentationStyle (.sheet / .fullScreen).
  • Header titleconfig.strings.chatHeaderTitle (defaults to "Voqal").
  • Iconsconfig.icons.chatHeaderIcon (header mark) and config.icons.voqalButtonIcon (the launcher). Leave unset for the accent orb.
  • Fast first turn — call VoqalSDKManager.shared.prewarm(delegate:) right after setup: it opens the engine connection in the background so the assistant is instant when the user opens it.
  • Conversation memoryconfig.conversationTimeout (default 2h): how long a conversation resumes after the sheet is closed & reopened.

Configuration reference

PropertyTypeDefaultDescription
requestIdStringrequiredEnvironment routing — prod- or stg- prefix.
apiKeyStringrequiredYour Voqal API key (pk_live_…), sent as X-Voqal-Key.
themeVoqalThemedefaultaccent, accent2, appearance (.light/.dark/.auto), fontName, radius.
homeVoqalHomeemptyuserName, pinnedCTAs, showAgentGlance.
presentationStylePresentationStyle.sheet.sheet (slide-up) or .fullScreen (edge-to-edge).
strings…StringsConfiguration"Voqal"chatHeaderTitle — the assistant's name in the header.
icons…IconConfigurationaccent orbchatHeaderIcon, voqalButtonIcon.
conversationTimeoutTimeInterval7200How long a conversation resumes after close/reopen (seconds).
agentURLURL?baked inOverride the engine endpoint (rarely needed).

API key & security

  • Every app needs a Voqal API key (pk_live_…), set on config.apiKey. We issue one per integrator — requests without a valid key are rejected.
  • Each session establishes a device key in the Secure Enclave and signs every request (proof-of-possession), so a leaked session token is useless without the device.
  • Money-movement actions are never executed inline — they surface a confirm card first. High-risk actions (e.g. instant settlement) additionally require Face ID; lower-risk ones (e.g. creating a payment link) are a single tap.
  • Session tokens refresh automatically and silently — no error is shown to the user.

Diagnostics

  • VoqalSDK includes built-in crash and error reporting so issues are detected and resolved quickly. It works automatically — no setup required.
  • It is privacy-preserving: auth tokens and personal data are never sent. You may wish to note the presence of in-app diagnostics in your privacy policy.

Need an API key?

We issue a Voqal API key per integrator. Reach out and we'll get you set up, or check the SDK repository for the latest release.