API reference
The API is the same on every platform, written in each platform’s idiom. The native iOS and Android SDKs implement the behaviour. React Native, Flutter and Unity forward to them and add a few helpers of their own.
Conventions
Section titled “Conventions”- Every call is fire-and-forget: it returns immediately and reports results through events.
- Every call is safe from any thread.
- Every call is safe before
initialize. It is remembered and applied when the SDK starts. The exception isshowSurvey, which reportsnot_initialized. - Listener callbacks and the display guard run on the main (UI) thread.
- Trait and property values are strings, numbers, booleans or dates. A
nullvalue removes a trait.
| Call | Behaviour |
|---|---|
initialize(sdkKey, options) | Starts the SDK: loads the cached configuration, downloads a new one when needed and applies the calls made so far. Options: apiHost, logLevel. Idempotent for the same key. A different key resets the local state first. |
identify(userId, traits) | Sets the user ID and merges the traits into the stored ones. Saved on the device. |
setAttributes(traits) | Merges traits without changing the user ID. A null value removes a trait. |
track(event, properties) | Adds one to the event’s count and evaluates event triggers. |
screen(name) | Sets the current screen and evaluates screen triggers. |
showSurvey(surveyId, options) | Shows a survey by its Survey ID. Options: force, hiddenFields, locale, presentation. Audience, schedule and frequency apply unless force is set. |
closeSurvey() | Closes the visible survey; it counts as dismissed unless it was completed. A survey that is still waiting or loading is cancelled without a callback, because it was never shown. |
pause() | Stops surveys started by triggers. showSurvey still works. Kept in memory only. |
resume() | Resumes surveys started by triggers. |
setLocale(tag) | Overrides the language for surveys and for the languages audience rule. null returns to the device language. Saved on the device. |
setHiddenFields(map) | Sets hidden-field values sent with every survey. Replaces the previous map. Saved on the device. |
setTrackingEnabled(enabled) | false switches the SDK off: no network, no targeting, nothing shown. Saved on the device and kept by reset. |
reset() | Clears the user ID, traits, language override, hidden fields, event counts, display history and cached configuration. Closes a visible survey. Keeps the install ID and the tracking setting. The SDK stays initialized. |
setDisplayGuard(guard) | Sets a function that is asked before a survey becomes visible and can veto it. No answer within 2 seconds counts as allow. Not asked for force. null removes it. |
addListener(listener) | Registers callbacks for the six events. |
removeListener(…) | Removes a listener. |
Guides: identify, track and screen, showSurvey, pause, display guard, closeSurvey, listeners, hidden fields, setLocale, setTrackingEnabled and reset.
Signatures
Section titled “Signatures”Swift, module ResponslySDK. All calls go through Responsly.shared.
import ResponslySDK
Responsly.shared.initialize(sdkKey: "rsk_…", options: ResponslyOptions(apiHost: URL(string: "https://api.responsly.com")!, logLevel: .debug))Responsly.shared.identify(userId: "user-123", traits: ["plan": "pro", "seats": 5, "beta": true, "signed_up": .date(Date())])Responsly.shared.setAttributes(["plan": "team", "beta": nil])Responsly.shared.track("purchase_completed", properties: ["value": 49.9])Responsly.shared.screen("Checkout")Responsly.shared.showSurvey("AbCd1234", options: ResponslyShowOptions(force: false, hiddenFields: ["order_id": "A-77"], locale: "pl", presentation: .dialog))Responsly.shared.closeSurvey()Responsly.shared.pause()Responsly.shared.resume()Responsly.shared.setLocale("pl") // nil = device languageResponsly.shared.setHiddenFields(["order_id": "A-77"])Responsly.shared.setTrackingEnabled(false)Responsly.shared.reset()Responsly.shared.setDisplayGuard { survey, decide in decide(!checkoutInProgress) }let token = Responsly.shared.addListener(MyListener()) // ResponslyListener protocol, all methods optionalResponsly.shared.removeListener(token)Responsly.sdkVersionResponslyListener methods:
func surveyShown(_ event: ResponslySurveyShownEvent)func surveyNotShown(_ event: ResponslySurveyNotShownEvent)func questionAnswered(_ event: ResponslyQuestionAnsweredEvent)func surveyCompleted(_ event: ResponslySurveyCompletedEvent)func surveyDismissed(_ event: ResponslySurveyDismissedEvent)func surveyError(_ event: ResponslySurveyErrorEvent)ResponslyListenerBlock is the closure-based variant. Every event has toDictionary(), which returns its fields with snake_case keys.
Swift specifics:
optionscan be left out ofinitializeandshowSurvey,traitsout ofidentifyandpropertiesout oftrack.ResponslyOptionsandResponslyShowOptionshave a default for every field; the default log level is.error.- Trait and property values are
ResponslyValue:.string,.number,.bool,.date. String, number and boolean literals convert automatically.ResponslyValue.from(_:),ResponslyValue.traits(from:)andResponslyValue.properties(from:)convert loosely typed values. reasonis aResponslyNotShownReason,trigger.typeaResponslyTriggerTypeandpresentationaResponslyPresentationStyle. TherawValueof each is the string listed on this page.trigger.nameis optional.- An answer’s
valueisAny:String,NSNumber, an array, a dictionary orNSNull. addListenerreturns aResponslyListenerToken. The SDK keeps the listener untilremoveListener(token).
Kotlin, callable from Java. Package com.responsly.sdk. All calls go through the Responsly object.
import com.responsly.sdk.*
Responsly.initialize(applicationContext, "rsk_…", ResponslyOptions(apiHost = "https://api.responsly.com", logLevel = LogLevel.DEBUG))Responsly.identify("user-123", mapOf("plan" to "pro", "seats" to 5, "beta" to true, "signed_up" to Date()))Responsly.setAttributes(mapOf("plan" to "team", "beta" to null))Responsly.track("purchase_completed", mapOf("value" to 49.9))Responsly.screen("Checkout")Responsly.showSurvey("AbCd1234", ShowOptions(force = false, hiddenFields = mapOf("order_id" to "A-77"), locale = "pl", presentation = PresentationStyle.DIALOG))Responsly.closeSurvey()Responsly.pause()Responsly.resume()Responsly.setLocale("pl") // null = device languageResponsly.setHiddenFields(mapOf("order_id" to "A-77"))Responsly.setTrackingEnabled(false)Responsly.reset()Responsly.setDisplayGuard { survey, decision -> if (checkoutInProgress) decision.veto() else decision.allow() }Responsly.addListener(listener) // ResponslyListener, all methods have defaultsResponsly.removeListener(listener)Responsly.SDK_VERSIONResponslyListener methods:
fun onSurveyShown(event: SurveyShownEvent)fun onSurveyNotShown(event: SurveyNotShownEvent)fun onQuestionAnswered(event: QuestionAnsweredEvent)fun onSurveyCompleted(event: SurveyCompletedEvent)fun onSurveyDismissed(event: SurveyDismissedEvent)fun onSurveyError(event: SurveyErrorEvent)Every event has toMap(), which returns its fields with snake_case keys.
reasonis aNotShownReasonenum; itsvalueis the string listed on this page (NotShownReason.FREQUENCY_LIMIT.value == "frequency_limit").options,traitsandpropertieshave defaults:Responsly.initialize(context, "rsk_…"),Responsly.showSurvey("AbCd1234")andResponsly.track("purchase_completed")are valid. The default log level isLogLevel.ERROR.
Package @responsly/react-native-sdk. The default export is the SDK object.
import Responsly, { useResponslyScreen, createNavigationTracker } from '@responsly/react-native-sdk'
Responsly.initialize('rsk_…', { apiHost: 'https://api.responsly.com', logLevel: 'debug' })Responsly.identify('user-123', { plan: 'pro', seats: 5, beta: true, signedUp: new Date() })Responsly.setAttributes({ plan: 'team', beta: null })Responsly.track('purchase_completed', { value: 49.9 })Responsly.screen('Checkout')Responsly.showSurvey('AbCd1234', { force: false, hiddenFields: { order_id: 'A-77' }, locale: 'pl', presentation: 'dialog' })Responsly.closeSurvey()Responsly.pause()Responsly.resume()Responsly.setLocale('pl') // null = device languageResponsly.setHiddenFields({ order_id: 'A-77' })Responsly.setTrackingEnabled(false)Responsly.reset()Responsly.setDisplayGuard((survey) => !checkoutInProgress) // boolean or Promise<boolean>; null removesconst unsubscribe = Responsly.addListener({ onSurveyShown: ({ survey, trigger }) => {}, onSurveyNotShown: ({ surveyId, reason }) => {}, onQuestionAnswered: ({ surveyId, questionId, type, title, value }) => {}, onSurveyCompleted: ({ surveyId, responseId, answers }) => {}, onSurveyDismissed: ({ surveyId }) => {}, onSurveyError: ({ surveyId, code, message }) => {},})unsubscribe()Additions of this package:
| Helper | Behaviour |
|---|---|
useResponslyScreen(name) | A hook. Calls screen(name) when the component mounts and whenever name changes. |
createNavigationTracker(navigationRef) | Returns { onReady, onStateChange } for React Navigation’s NavigationContainer. Calls screen with the active route name whenever it changes. |
Event payloads are camelCase in JavaScript. Date values are sent as ISO 8601 strings.
Package responsly_sdk. All calls are static methods of Responsly and return Future<void>.
import 'package:responsly_sdk/responsly_sdk.dart';
await Responsly.initialize('rsk_…', options: const ResponslyOptions(apiHost: 'https://api.responsly.com', logLevel: ResponslyLogLevel.debug));Responsly.identify('user-123', traits: {'plan': 'pro', 'seats': 5, 'beta': true, 'signed_up': DateTime.now()});Responsly.setAttributes({'plan': 'team', 'beta': null});Responsly.track('purchase_completed', properties: {'value': 49.9});Responsly.screen('Checkout');Responsly.showSurvey('AbCd1234', force: false, hiddenFields: {'order_id': 'A-77'}, locale: 'pl', presentation: ResponslyPresentation.dialog);Responsly.closeSurvey();Responsly.pause();Responsly.resume();Responsly.setLocale('pl'); // null = device languageResponsly.setHiddenFields({'order_id': 'A-77'});Responsly.setTrackingEnabled(false);Responsly.reset();Responsly.setDisplayGuard((survey) async => !checkoutInProgress); // null removesfinal subscription = Responsly.events.listen((event) { switch (event) { case SurveyShown(:final survey, :final trigger): break; case SurveyNotShown(:final surveyId, :final reason): break; case QuestionAnswered(:final surveyId, :final questionId, :final type, :final title, :final value): break; case SurveyCompleted(:final surveyId, :final responseId, :final answers): break; case SurveyDismissed(:final surveyId): break; case SurveyError(:final surveyId, :final code, :final message): break; }});Additions of this package:
| Member | Behaviour |
|---|---|
Responsly.events | A broadcast Stream<ResponslyEvent>. ResponslyEvent is a sealed class with the six event types above. It replaces addListener / removeListener. |
ResponslyNavigatorObserver() | For MaterialApp(navigatorObservers: […]). Calls screen with the route’s settings.name on push, pop and replace. Routes without a name are skipped. |
UPM package com.responsly.sdk, namespace Responsly. All calls are static methods of ResponslySDK.
using Responsly;using System.Collections.Generic;
ResponslySDK.Initialize("rsk_…", new ResponslyOptions { ApiHost = "https://api.responsly.com", LogLevel = ResponslyLogLevel.Debug });ResponslySDK.Identify("user-123", new Dictionary<string, object> { { "plan", "pro" }, { "level", 12 }, { "beta", true } });ResponslySDK.SetAttributes(new Dictionary<string, object> { { "plan", "team" }, { "beta", null } });ResponslySDK.Track("level_completed", new Dictionary<string, object> { { "level", 12 } });ResponslySDK.Screen("MainMenu");ResponslySDK.ShowSurvey("AbCd1234", new ShowOptions { Force = false, HiddenFields = new Dictionary<string, string> { { "run_id", "42" } }, Locale = "pl", Presentation = ResponslyPresentation.Dialog });ResponslySDK.CloseSurvey();ResponslySDK.Pause();ResponslySDK.Resume();ResponslySDK.SetLocale("pl"); // null = device languageResponslySDK.SetHiddenFields(new Dictionary<string, string> { { "run_id", "42" } });ResponslySDK.SetTrackingEnabled(false);ResponslySDK.Reset();ResponslySDK.SetDisplayGuard(survey => !inBossFight); // Func<ResponslySurvey, bool>; null removes
ResponslySDK.SurveyShown += e => { Time.timeScale = 0; }; // e.Survey.Id, e.Survey.Name, e.Trigger.Type, e.Trigger.NameResponslySDK.SurveyNotShown += e => { }; // e.SurveyId, e.ReasonResponslySDK.QuestionAnswered += e => { }; // e.SurveyId, e.QuestionId, e.Type, e.Title, e.ValueJsonResponslySDK.SurveyCompleted += e => { Time.timeScale = 1; }; // e.SurveyId, e.ResponseId, e.AnswersResponslySDK.SurveyDismissed += e => { Time.timeScale = 1; }; // e.SurveyIdResponslySDK.SurveyError += e => { }; // e.SurveyId, e.Code, e.Message- Callbacks are C# events raised on Unity’s main thread. They replace
addListener/removeListener. - Answer values are JSON text in
ValueJson, with the typed helpersAsString(),AsDouble()andAsBool()on the event (QuestionAnsweredEventArgs) and on eachResponslyAnswerine.Answers. A helper returnsnullwhen the value is not of that type. - In the Editor and on platforms other than iOS and Android, every call is a no-op that logs at the
Debuglevel.
Events
Section titled “Events”All events are delivered on the main thread. Field names are shown in camelCase; Unity uses PascalCase (e.SurveyId), and toDictionary() / toMap() on iOS and Android use snake_case keys (survey_id).
| Event | Fires when | Fields |
|---|---|---|
surveyShown | The survey became visible. | survey.id, survey.name, trigger.type, trigger.name |
surveyNotShown | A survey matched a trigger or was requested with showSurvey, but was not shown. | surveyId, reason |
questionAnswered | The respondent answered a question. | surveyId, questionId, type, title, value |
surveyCompleted | The respondent submitted the survey. | surveyId, responseId, answers[] (questionId, type, title, value) |
surveyDismissed | The survey was closed before it was completed. | surveyId |
surveyError | The survey reported an error while it was visible. | surveyId, code, message |
Names per platform:
| Event | iOS | Android, React Native | Flutter, Unity |
|---|---|---|---|
| Shown | surveyShown | onSurveyShown | SurveyShown |
| Not shown | surveyNotShown | onSurveyNotShown | SurveyNotShown |
| Question answered | questionAnswered | onQuestionAnswered | QuestionAnswered |
| Completed | surveyCompleted | onSurveyCompleted | SurveyCompleted |
| Dismissed | surveyDismissed | onSurveyDismissed | SurveyDismissed |
| Error | surveyError | onSurveyError | SurveyError |
On iOS, Android and React Native these are listener methods. In Flutter they are the event classes of Responsly.events, and in Unity they are C# events on ResponslySDK.
Field details and the order of events are in Callbacks.
Initialization options
Section titled “Initialization options”| Field | Type | Description |
|---|---|---|
apiHost | URL (URL in Swift, a string elsewhere) | Base address of the Responsly API. Defaults to https://api.responsly.com. Change it only when Responsly support tells you to. |
logLevel | Log level | How much the SDK logs. |
The type is ResponslyOptions on iOS, Android, Flutter and Unity, and a plain object in React Native.
Show options
Section titled “Show options”| Field | Type | Description |
|---|---|---|
force | boolean, default false | Skip audience, schedule, frequency and the display guard. |
hiddenFields | map of string to string | Hidden-field values for this survey only. Combined with the setHiddenFields map; the per-call value wins for a key present in both. |
locale | language tag | Language for this survey only. |
presentation | Presentation style | Overrides the style set in the Mobile app tab. |
The type is ResponslyShowOptions on iOS and ShowOptions on Android and Unity. React Native takes a plain object. Flutter takes them as named parameters of showSurvey.
Presentation styles
Section titled “Presentation styles”The styles are bottom_sheet, dialog and fullscreen.
| Platform | Values |
|---|---|
| iOS | .bottomSheet, .dialog, .fullscreen |
| Android | PresentationStyle.BOTTOM_SHEET, PresentationStyle.DIALOG, PresentationStyle.FULLSCREEN |
| React Native | 'bottom_sheet', 'dialog', 'fullscreen' |
| Flutter | ResponslyPresentation.bottomSheet, ResponslyPresentation.dialog, ResponslyPresentation.fullscreen |
| Unity | ResponslyPresentation.BottomSheet, ResponslyPresentation.Dialog, ResponslyPresentation.Fullscreen |
Layouts and sizes are described in Appearance.
Log levels
Section titled “Log levels”The levels are none, error, info and debug, from silent to everything.
| Platform | Values |
|---|---|
| iOS | .none, .error, .info, .debug |
| Android | LogLevel.NONE, LogLevel.ERROR, LogLevel.INFO, LogLevel.DEBUG |
| React Native | 'none', 'error', 'info', 'debug' |
| Flutter | ResponslyLogLevel.none, ResponslyLogLevel.error, ResponslyLogLevel.info, ResponslyLogLevel.debug |
| Unity | ResponslyLogLevel.None, ResponslyLogLevel.Error, ResponslyLogLevel.Info, ResponslyLogLevel.Debug |
What each level logs is described in Testing & debugging.
Trait and property values
Section titled “Trait and property values”Values are strings, numbers, booleans or dates. A null value (nil in Swift) removes a trait.
| Platform | String | Number | Boolean | Date |
|---|---|---|---|---|
| iOS | "pro" | 5, 49.9 | true | .date(Date()) |
| Android | String | Int, Long, Double | Boolean | java.util.Date |
| React Native | string | number | boolean | Date |
| Flutter | String | int, double | bool | DateTime |
| Unity | string | int, double | bool | ISO 8601 UTC string |
Dates are stored and compared in UTC with seconds precision, as 2026-11-10T12:00:00Z.
Survey
Section titled “Survey”Passed to the display guard and included in surveyShown. The type is ResponslySurvey on iOS and Unity.
| Field | Description |
|---|---|
id | The Survey ID. |
name | The form’s name in Responsly. |
Trigger
Section titled “Trigger”Included in surveyShown.
| Field | Description |
|---|---|
type | event, screen, app_launch, or manual for showSurvey. |
name | The event or screen name. null (absent on iOS) for app_launch and manual. |
Answer
Section titled “Answer”An item of answers in surveyCompleted. questionAnswered carries the same four fields.
| Field | Description |
|---|---|
questionId | The question’s ID. |
type | The question’s type, for example nps, rating, multiple_choice, text. |
title | The question text. |
value | The answer as the survey stores it: a string, number, boolean, list or map. Number scales give a number. |
Not-shown reasons
Section titled “Not-shown reasons”The reason of surveyNotShown is one of:
disabled, not_initialized, config_unavailable, survey_not_found, another_survey_visible, another_survey_selected, paused, outside_schedule, platform_mismatch, app_mismatch, locale_mismatch, audience_mismatch, already_completed, frequency_limit, recontact_wait, global_cooldown, sampled_out, screen_changed, vetoed, load_failed, survey_unavailable.
Each one is explained, with a fix, in Testing & debugging.
SDK version
Section titled “SDK version”| Platform | Constant |
|---|---|
| iOS | Responsly.sdkVersion |
| Android | Responsly.SDK_VERSION |