Configuration

Last updated  Aug 4, 2026

One configuration object drives the whole experience. The model is identical on iOS, Android, and Flutter — examples below are Swift; the other platforms use the same names.

Theming

One VoqalTheme drives every surface. Hairlines, text tiers, and fills are derived automatically so the assistant looks native in light or dark.

Theme.swift
config.theme = VoqalTheme(    accent: "#2d5bff",        // your brand color (hex)    accent2: "#5b8dff",       // optional gradient pair    appearance: .auto,        // .light · .dark · .auto (follows the phone)    font: nil,                // your app's font — one font for ALL text    radius: 20)               // base corner radius for cards & the sheet

Presentation style

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.swift
config.presentationStyle = .fullScreen   // default: .sheet

Header branding

Replace the default “Voqal” title and mark with your own. Leave both unset to fall back to the Voqal title and mark.

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

Action button

Optionally show an accent-colored button next to the voice wave that takes the user to a page in your app — a checkout screen, for example. The SDK renders the button; your app owns the route. Off by default.

AppDelegate.swift
// Enable the button (nil icon → a default shopping-bag glyph).config.actionButton = VoqalActionButton(icon: UIImage(named: "Cart"))// Navigate from your own view controller when it's tapped.func voqalDidTapActionButton() {    let checkout = CheckoutViewController()    getViewController().present(checkout, animated: true)}
When tapped, the SDK dismisses the assistant first unless you pass dismissOnTap: false, then calls you back.

Redirect & checkout

There is no single “checkout button” setting — sending a user to a payment or a destination happens one of three ways, depending on who owns the flow. Pick the one that matches where the action lives.

MechanismWho renders itCarries a payload?
Action buttonSDK chrome, your app navigatesNo — a plain tap into your own flow
Confirm widgetEngine emits it, SDK executes itYes — title, price, CTA, action
Automatic link cardSDK, from a URL in the answerYes — the URL itself
  • Action button — the accent button next to the voice wave (see config.actionButton above). On tap the SDK calls your voqalDidTapActionButton callback and your app pushes its own checkout screen. It carries no conversation payload; use it for a fixed destination like a cart or a settings page.
  • Confirm widget— for an action the agent proposes in-conversation (“create a 500 EGP payment link”), the engine emits a single confirm card with the title, amount, and call-to-action. The user confirms it and the SDK runs it via /voqal/execute. You render nothing and author no card — the engine owns the copy and the payload.
  • Automatic link card — any http(s)URL in the agent’s answer becomes a tappable card the SDK opens with the OS URL handler. Return a checkout link from your backend and it is presented automatically — no widget, no config.
Biometric tiering. A high-risk confirm (money movement) sets requiresBiometric, so the SDK gates it behind Face ID / Touch ID before executing; low-risk actions are tap-to-confirm. The engine decides the tier per action — you do not configure it, and the agent never names the method aloud.

Forwarding headers to your backend

Two header channels leave the SDK, and they go to different places — this is the distinction to get right. One is read by the Voqal engine; the other is passed straight through to your backend untouched.

ChannelRead byWhat it carries
X-Client-MetadataThe Voqal engineOpaque JSON context — country_code, user_id — for locale and personalization.
X-Voqal-Forward-*Your own backend / MCPVerbatim passthrough. The engine strips the prefix and forwards the original header as-is.

Metadatais set through the SDK’s metadata hook and never reaches your backend as a header; the engine consumes it. Forwarded headers (new in 2.0.0) are the seamless way to hand your backend whatever it needs to authenticate a request — no dashboard configuration. You return a plain map; the SDK sends each entry namespaced as X-Voqal-Forward-<Name>, and the engine strips the prefix and forwards <Name> to your backend on every call.

Checkout.swift
// Return the headers YOUR backend needs. Read live — called every request.func voqalForwardedHeaders() -> [String: String] {    return [        "Authorization": "Bearer \(session.accessToken)",        "X-Tenant-Id": tenantId,    ]}

The hook is named per platform, and each platform exposes both channels:

PlatformMetadata hook (engine)Forwarded-headers hook (your backend)
iOSgetMetaData()voqalForwardedHeaders()
AndroidgetMetadata()getForwardedHeaders()
FluttermetadataJsonforwardedHeaders
React NativemetadataJsonforwardedHeaders
  • Read live, every request — the hook is called on each turn, so a rotated or refreshed token is always current. Never cache a stale value.
  • Authorization is forwardable — return it like any other header and your backend receives it as Authorization.
  • Reserved control headers are dropped X-Token, X-Voqal-Key, X-Request-ID, X-Client-Metadata, Content-Type, and Accept can never be overridden by a forwarded header.
  • Bounded — at most 32 headers per request; excess is dropped rather than failing the turn.
  • Destination-scoped— forwarded headers reach only your tenant’s own backend, never anywhere else.

Home screen

The greeting name, the “Try saying” suggestions, and whether the live data glance shows when the assistant opens.

AppDelegate.swift
config.home = VoqalHome(    userName: "Nour",    pinnedCTAs: ["What's my balance?", "Create a payment link"],    showAgentGlance: true)

Configuration reference

PropertyTypeDefaultDescription
requestIdStringrequiredEnvironment routing — prod- or stg- prefix.
apiKeyStringrequiredYour Voqal API key (pk_live_…), sent as X-Voqal-Key.
themeVoqalThemedefaultaccent, accent2, appearance, font, radius.
homeVoqalHomeemptyuserName, pinnedCTAs, showAgentGlance.
presentationStylePresentationStyle.sheet.sheet (slide-up) or .fullScreen (edge-to-edge).
stringsStringsConfiguration“Voqal”chatHeaderTitle— the assistant’s name in the header.
iconsIconConfigurationaccent orbchatHeaderIcon, voqalButtonIcon.
actionButtonVoqalActionButton?offOptional in-app navigation button next to the voice wave.
conversationTimeoutTimeInterval7200How long a conversation resumes after close and reopen (seconds).
agentURLURL?baked inOverride the engine endpoint (rarely needed).
  • Fast first turn — call prewarm right after setup: it opens the engine connection in the background so the assistant is instant when opened.
  • Conversation memoryconversationTimeout (default 2h) controls how long a conversation resumes after the sheet is closed and reopened.
© 2026 VoqalVoqal SDK & engine documentation