> For the complete documentation index, see [llms.txt](https://cmp.docs.sirdata.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cmp.docs.sirdata.net/en/mobile-apps-native-sdk/mobile-sdk/reference-1.md).

# iOS — Reference

Every method and event exposed by the iOS SDK. Setup and the recommended integration order live in [Setup](/en/mobile-apps-native-sdk/mobile-sdk/setup-1.md).

## iOS SDK — `IosCMPApi`

The primary interface for iOS publishers. All methods delegate to the `IosCMPManager` singleton.

`import SirDataCMP`, then call through `IosCMPApi.shared`. The signatures below are written as Swift sees them in the framework's exported header: Kotlin `Int` is `Int32`, `Long` is `Int64`, and a Kotlin `suspend` function is both `async throws` and a `completionHandler:` variant. The only error those variants pass on is a Kotlin `CancellationException` — in the next release, `acceptAll`, `rejectAll`, `saveConsent` and `submitConsent` also pass on the `IllegalStateException` raised before `initialize`.

**Call `initialize` exactly once, on the main thread, before any other SDK call.** Kotlin exceptions are not converted to Swift errors: a misuse that throws in Kotlin terminates the app. That is the case of a second `initialize` (without `shutdown()` in between), and of any of these calls before `initialize`: `getConsentState()`, `getConsentData()`, `getConsentUpdates()`, `getLastTcStringError()`, `discardPendingChanges()`, `getGoogleConsentState()`, `getLastForwardedConsentState()`, `getRegisteredAdapters()`, `acceptAll()`, `rejectAll()`, `saveConsent()`, `submitConsent(userAction:)`, and creating a `ConsentView`. This is 2.0.0 behaviour. In the next release (unreleased) none of these terminates the app: the getters return a neutral value, the four submissions throw a Swift error, a second `initialize` is ignored and logged, and `ConsentView` shows a message with a Close button.

### Initialization

| Method          | Signature                                             | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialize`    | `func initialize(partnerId: Int32, configId: String)` | Initialize with partner credentials. Main thread only. Writes `IABTCF_CmpSdkID`, `IABTCF_CmpSdkVersion` and `IABTCF_PolicyVersion` to NSUserDefaults immediately, then loads the publisher configuration asynchronously; the keys written once it has loaded, before any choice, are listed in [Setup](/en/mobile-apps-native-sdk/mobile-sdk/setup-1.md#values). A second call without `shutdown()` terminates the app in 2.0.0; the next release ignores it and logs it. |
| `initialize`    | `func initialize(config: IosCMPConfig)`               | Same, with a full configuration object — see `IosCMPConfig` below.                                                                                                                                                                                                                                                                                                                                                                                                        |
| `isInitialized` | `func isInitialized() -> Bool`                        | Returns `true` once `initialize` has been called, before the configuration has loaded.                                                                                                                                                                                                                                                                                                                                                                                    |
| `getInitError`  | `func getInitError() -> String?`                      | `nil` while the configuration loads and after it loaded; the error message once a load has failed (unknown config ID, network down…). Cleared by the next `initialize`. In 2.0.0 it is set a moment after `getConsentState()` turns `READY`; the next release sets it before, so it is there when `awaitConsentDisplayDecision()` returns. The failure is not logged on iOS — see [Logging](/en/mobile-apps-native-sdk/mobile-sdk/logging.md).                            |
| `shutdown`      | `func shutdown()`                                     | Clears in-memory state and cancels a configuration load in flight. Stored consent stays in NSUserDefaults. Main thread only.                                                                                                                                                                                                                                                                                                                                              |

### Banner Events

| Method               | Signature                   | Description                                                                                                                                              |
| -------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `notifyBannerShown`  | `func notifyBannerShown()`  | Fires `cmpuishown` event. Call it each time you present `ConsentView`, just before presenting it.                                                        |
| `notifyBannerClosed` | `func notifyBannerClosed()` | Fires `cmpuiclosed` to TCF and GPP listeners. `ConsentView` calls it itself when it finishes or is dismissed: call it only for a consent UI of your own. |

### Consent Submission

All five need an initialized SDK.

| Method                  | Signature                                                                          | Returns         | Description                                                                                                                                                                                                     |
| ----------------------- | ---------------------------------------------------------------------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `acceptAll`             | `func acceptAll() async throws -> ConsentResult`                                   | `ConsentResult` | Accept all purposes, vendors, and features.                                                                                                                                                                     |
| `rejectAll`             | `func rejectAll() async throws -> ConsentResult`                                   | `ConsentResult` | Reject all purposes, vendors, and features.                                                                                                                                                                     |
| `saveConsent`           | `func saveConsent() async throws -> ConsentResult`                                 | `ConsentResult` | Save current selections.                                                                                                                                                                                        |
| `submitConsent`         | `func submitConsent(userAction: UserActionResponse) async throws -> ConsentResult` | `ConsentResult` | Records the current selections and reports them with the given answer.                                                                                                                                          |
| `discardPendingChanges` | `func discardPendingChanges()`                                                     | —               | Discards the selections changed since the last recorded choice. Call it right before submitting when the user declines to apply pending changes, as the "do not apply" button of the apply-choices banner does. |

Each recorded choice fires `useractioncomplete` to TCF and GPP listeners and forwards the Google consent signals to the [consent adapters](/en/mobile-apps-native-sdk/mobile-sdk/sharing-consent.md#consent-adapters).

### Consent State Queries

| Method                            | Signature                                                                                       | Returns                                                                                                                                                                                                                                                                                                                                                                                              |
| --------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `getTcString`                     | `func getTcString() -> String`                                                                  | IAB TC String                                                                                                                                                                                                                                                                                                                                                                                        |
| `getGppString`                    | `func getGppString() -> String`                                                                 | GPP String                                                                                                                                                                                                                                                                                                                                                                                           |
| `getUspString`                    | `func getUspString() -> String`                                                                 | USP String — empty when no US choice has been recorded                                                                                                                                                                                                                                                                                                                                               |
| `getAddtlConsent`                 | `func getAddtlConsent() -> String`                                                              | Additional Consent String                                                                                                                                                                                                                                                                                                                                                                            |
| `isGdprApplies`                   | `func isGdprApplies() -> Bool`                                                                  | GDPR applicability — `context.gdprApplies` from the API once loaded, device geo before                                                                                                                                                                                                                                                                                                               |
| `isCcpaApplies`                   | `func isCcpaApplies() -> Bool`                                                                  | US Privacy applicability — `context.ccpaApplies` from the API once the configuration has loaded (from the visitor's country and US state), device geo before                                                                                                                                                                                                                                         |
| `shouldCollectConsent`            | `func shouldCollectConsent() -> Bool`                                                           | Web `checkConsent()` cascade, answered immediately (provisional before the config lands)                                                                                                                                                                                                                                                                                                             |
| `getConsentDisplayDecision`       | `func getConsentDisplayDecision() -> ConsentDisplayDecision`                                    | `shouldDisplay` + `workflow` + `reason`, also immediate — see [Display decision](#display-decision)                                                                                                                                                                                                                                                                                                  |
| `awaitConsentDisplayDecision`     | `func awaitConsentDisplayDecision() async throws -> ConsentDisplayDecision`                     | Waits for the config, then decides. Swift: `try await`                                                                                                                                                                                                                                                                                                                                               |
| `awaitConsentDisplayDecision`     | `func awaitConsentDisplayDecision(timeoutMillis: Int64) async throws -> ConsentDisplayDecision` | Same, bounded                                                                                                                                                                                                                                                                                                                                                                                        |
| `recordPrompt` / `recordAskLater` | `func recordPrompt()` / `func recordAskLater()`                                                 | Restart the `cappingInDays` window (only for a re-open the user asked for; `ConsentView` with `.manualDisplay` already does it) / record an explicit "ask me later", which hides the banner for **one hour**, a fixed duration, and records no consent. Both do nothing before `initialize`                                                                                                          |
| `getConsentState`                 | `func getConsentState() -> any Kotlinx_coroutines_coreStateFlow`                                | Observable state flow — observe it with `ConsentStateWatcher`. Needs an initialized SDK                                                                                                                                                                                                                                                                                                              |
| `getConsentData`                  | `func getConsentData() -> ConsentData`                                                          | Full consent data. Needs an initialized SDK                                                                                                                                                                                                                                                                                                                                                          |
| `getConsentUpdates`               | `func getConsentUpdates() -> any Kotlinx_coroutines_coreStateFlow`                              | Counter bumped on every change to the selections — each toggle in the consent UI, before the user saves, as well as each recorded choice. A US choice (the US screen, or `setCcpaOptOut`) does not bump it: re-read `getUspString()` and `getGppString()` when the consent UI closes. A Kotlin flow cannot be collected from Swift: observe it with `UpdateCounterWatcher`. Needs an initialized SDK |
| `getLastTcStringError`            | `func getLastTcStringError() -> String?`                                                        | Outcome of the last server archive of a recorded choice (`/consent-string`): `nil` when it succeeded or none has run, otherwise a message starting with `/consent-string`. Set in the background after `submitConsent` returns. Despite its name, it does not report on the TC string, which is encoded on the device. Needs an initialized SDK                                                      |
| `getPurposeConsents`              | `func getPurposeConsents() -> String`                                                           | Purpose consents bit field                                                                                                                                                                                                                                                                                                                                                                           |
| `getVendorConsents`               | `func getVendorConsents() -> String`                                                            | Vendor consents bit field                                                                                                                                                                                                                                                                                                                                                                            |
| `hasPurposeConsent`               | `func hasPurposeConsent(purposeId: Int32) -> Bool`                                              | Check purpose consent                                                                                                                                                                                                                                                                                                                                                                                |
| `hasVendorConsent`                | `func hasVendorConsent(vendorId: Int32) -> Bool`                                                | Check vendor consent                                                                                                                                                                                                                                                                                                                                                                                 |

### Google Consent Mode and adapters

All three need an initialized SDK.

| Method                         | Signature                                                    | Returns                                                                                                      |
| ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `getGoogleConsentState`        | `func getGoogleConsentState() -> GoogleConsentState`         | The Google consent signals computed from the current selections: what the adapters would receive             |
| `getLastForwardedConsentState` | `func getLastForwardedConsentState() -> GoogleConsentState?` | What was actually forwarded to the adapters, or `nil` when no choice has been recorded since `initialize`    |
| `getRegisteredAdapters`        | `func getRegisteredAdapters() -> [String]`                   | The adapters whose SDK is linked into the app: `"Firebase Analytics"`, `"AppsFlyer"`, `"Adjust"`, `"Branch"` |

`GoogleConsentState` carries `adStorageGranted`, `analyticsStorageGranted`, `adUserDataGranted`, `adPersonalizationGranted`, `personalizationStorageGranted`, `functionalityStorageGranted`, `securityStorageGranted`, `isSubjectToGDPR`, `hasConsentForDataUsage` and `adSignalsFromTcf` — `true` when the configuration leaves the three ad signals to Google, in which case the Firebase adapter does not send them. See [Sharing consent with vendor SDKs](/en/mobile-apps-native-sdk/mobile-sdk/sharing-consent.md).

### Observing changes from Swift

The two Kotlin flows above are observed through watchers. Each calls its block on the main thread; keep the watcher alive while you need it, and call `close()` when done. Calling `watch` again replaces the previous block.

| Watcher                | Signature                                                                                                                 | Description                                                                                                                                                        |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `UpdateCounterWatcher` | `init(flow: any Kotlinx_coroutines_coreStateFlow)`, `func watch(block: @escaping (KotlinLong) -> Void)`, `func close()`   | For `getConsentUpdates()`. Skips the current value: the block runs on the next change, not at startup. A burst of changes, such as one tap on a stack, is batched. |
| `ConsentStateWatcher`  | `init(flow: any Kotlinx_coroutines_coreStateFlow)`, `func watch(block: @escaping (ConsentState) -> Void)`, `func close()` | For `getConsentState()`. Delivers the current state, then every change.                                                                                            |

```swift
// After initialize. The watcher fires on the next change, not now: apply once first.
applyConsentGate()
let watcher = UpdateCounterWatcher(flow: IosCMPApi.shared.getConsentUpdates())
watcher.watch { _ in applyConsentGate() } // re-read the stored values here
// … later
watcher.close()
```

### IAB API Access

| Method     | Returns         | Description        |
| ---------- | --------------- | ------------------ |
| `tcfApi()` | `TcfApiHandler` | IAB TCF CMP API v2 |
| `gppApi()` | `GppApiHandler` | GPP API            |
| `uspApi()` | `UspApiHandler` | USP/CCPA API       |

The commands and their data are the same as on Android — see the command tables in [Reference — Android](/en/mobile-apps-native-sdk/mobile-sdk/reference.md). The TCF and GPP handlers call back on the main thread; `getUspData` calls back synchronously, on the calling thread. Their Swift signatures:

```swift
// TcfApiHandler
func execute(command: String, version: Int32,
             callback: @escaping (Any?, Any?, KotlinBoolean) -> Void, parameter: Any?)

// GppApiHandler
func execute(command: String, parameter: Any?, callback: @escaping (Any?, KotlinBoolean) -> Void)

// UspApiHandler
func execute(command: String, version: Int32,
             callback: @escaping ([String: Any]?, KotlinBoolean) -> Void, parameter: Any?)
```

The success flag is a `KotlinBoolean`: read it with `success.boolValue`. TCF listener callbacks carry no `eventStatus` in 2.0.0 — see [the in-app command API](/en/mobile-apps-native-sdk/mobile-sdk/sharing-consent.md#the-in-app-command-api).

### CCPA Opt-Out

| Method                          | Description                                                                                                                                                                                                                                                                                                                                          |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setCcpaOptOut(optedOut: Bool)` | Records the user's "Do Not Sell" choice: writes `IABUSPrivacy_String` and, once the SDK is initialized, re-encodes the GPP string (sections 6 and 7). Call it from a control the user operates, never on their behalf. Main thread only. The consent UI's US screen calls it when the user saves. It does not bump the `getConsentUpdates()` counter |
| `isCcpaOptedOut() -> Bool`      | Returns opt-out status                                                                                                                                                                                                                                                                                                                               |

### Data Management

| Method           | Description                                      |
| ---------------- | ------------------------------------------------ |
| `clearConsent()` | Clears ALL persisted consent from NSUserDefaults |

***

## `IosCMPConfig` — iOS Configuration

| Field                | Swift type | Default                                                          |
| -------------------- | ---------- | ---------------------------------------------------------------- |
| `partnerId`          | `Int32`    | required — your Sirdata partner ID                               |
| `configId`           | `String`   | required — your Sirdata config ID                                |
| `language`           | `String?`  | `nil` — accepted, no effect in 2.0.0                             |
| `apiRoot`            | `String`   | `"https://api.consentframework.com/api/v1/public"`               |
| `cacheApiRoot`       | `String`   | `"https://choices.consentframework.com/api/v1/public"`           |
| `consentApiRoot`     | `String`   | `"https://mychoice.consentframework.com/api/v1/public"`          |
| `debugMode`          | `Bool`     | `false` — main-thread violations throw, which terminates the app |
| `gdprDefaultApplies` | `Bool`     | `true` — see below                                               |

The defaults are Kotlin defaults, which Swift does not see: the `IosCMPConfig` initializer takes every argument — `partnerId:configId:language:apiRoot:cacheApiRoot:consentApiRoot:debugMode:gdprDefaultApplies:`. Use the builder instead.

* **`language`** is accepted but read by nothing in 2.0.0. The UI language is the one pinned in the publisher configuration in the Sirdata Console, if any; otherwise the device language, when the SDK supports it; otherwise the configuration's default language; otherwise English.
* **`debugMode`** only changes the main-thread contract: a call to `initialize`, `shutdown` or `setCcpaOptOut` off the main thread throws instead of being logged — and on iOS that terminates the app. Debug builds only.
* **`gdprDefaultApplies`** is the answer `isGdprApplies()` gives before the publisher configuration has loaded, when the device reports no region. Once the configuration has loaded, the API decides.
* The iOS configuration has no theme option: the consent UI takes its colors from the theme configured in the Sirdata Console, in its light or dark version according to the system appearance (the light one when no dark version is configured). It has no certificate pinning option either.

### Builder

```swift
// partnerId is an Int32. The three hosts below are the defaults.
let config = IosCMPConfig.Builder(partnerId: partnerId, configId: configId)
    .apiRoot(apiRoot: "https://api.consentframework.com/api/v1/public")
    .cacheApiRoot(cacheApiRoot: "https://choices.consentframework.com/api/v1/public")
    .consentApiRoot(consentApiRoot: "https://mychoice.consentframework.com/api/v1/public")
    .gdprDefaultApplies(gdprDefaultApplies: true)
    #if DEBUG
    .debugMode(debugMode: true) // debug builds only
    #endif
    .build()
IosCMPApi.shared.initialize(config: config)
```

The builder also has `language(language:)`, which has no effect in 2.0.0.

***

## SwiftUI — `ConsentView`

`import SirDataCMPUI`. The consent UI: banner, purposes and partners screens, and the US screen when US Privacy applies. Its initializer, as declared in `SirDataCMPUI`:

```swift
public init(
    onFinish: @escaping () -> Void,
    initialScreen: ConsentScreen? = nil,
    workflow: Workflow? = nil
)
```

| Parameter       | Description                                                                                                                                                                                                                                                                                                                                                                   |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onFinish`      | Called when the user is done with the banner. Dismiss your presentation there.                                                                                                                                                                                                                                                                                                |
| `initialScreen` | Screen to open once the CMP is loaded, for example `.purposes` to open the preferences directly. `nil` (the default) opens the banner.                                                                                                                                                                                                                                        |
| `workflow`      | `nil` (the default) asks the display decision, so a partially answered consent opens in "apply choices" mode. Pass `.manualDisplay` when re-opening from a settings screen: the banner shows the close cross at the top and a "Reject all" button whatever the refusal type the publisher configured, restarts the `cappingInDays` window, and is reported as `load:revisit`. |

* Call `IosCMPApi.shared.notifyBannerShown()` just before presenting it. `ConsentView` fires `cmpuiclosed` itself.
* Dismissing it without one of its buttons — swiping its sheet down, or pushing another view over it — records nothing: it is reported like the close button that saves nothing, and the banner comes back on the next launch.
* Creating it before `initialize` terminates the app in 2.0.0. The next release shows a message with a Close button instead.
* Known issue in 2.0.0: when the configuration could not be loaded at this launch (offline, for instance), it shows only a loading indicator, with no close control. A `.sheet` can still be swiped down; with `.interactiveDismissDisabled()` or in a full-screen presentation, nothing closes it. Present it in those two ways only when `IosCMPApi.shared.tcfApi().isCmpLoaded()` is `true` — see [Setup](/en/mobile-apps-native-sdk/mobile-sdk/setup-1.md#closing-the-sheet-without-answering). Fixed in the next release: a message and a Close button, and a Close button under the loading indicator after five seconds.

### `ConsentScreen`

| Value                             | Description                                                                |
| --------------------------------- | -------------------------------------------------------------------------- |
| `.main`                           | The banner                                                                 |
| `.purposes`                       | The purposes screen                                                        |
| `.vendors`                        | The partners screen                                                        |
| `.purposeOne`                     | The purpose 1 screen of the cookie wall                                    |
| `.mainMissing`, `.vendorsMissing` | Not entry screens: values recorded in the TC string's consent screen field |

***

## Display decision

`ConsentDisplayDecision` has three properties: `shouldDisplay: Bool`, `workflow: Workflow` (pass it to `ConsentView`) and `reason: DisplayReason`.

| `Workflow`          | Description                                                                                                            |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `.main`             | The standard banner. Also the workflow of every decision that does not display.                                        |
| `.applyChoices`     | Returned when the stored choice is missing only partners: the banner asks only about what is left to decide.           |
| `.cookiewall`       | Returned when the configuration enables the cookie wall and the stored choice does not grant purpose 1.                |
| `.cookiewallModify` | Set by the consent UI itself when the user modifies their choices from the cookie wall. The decision never returns it. |
| `.manualDisplay`    | Re-opening from a settings screen, passed by the app. The decision never returns it.                                   |

| `DisplayReason`    | `shouldDisplay`   | Meaning                                                                                                                          |
| ------------------ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `.gdprNotApplies`  | `false`           | GDPR does not apply.                                                                                                             |
| `.consentRequired` | `true`            | Something is left to ask.                                                                                                        |
| `.cappingActive`   | `false`           | A capping window is running on a stored choice that does not grant purpose 1.                                                    |
| `.cappingAskLater` | `false`           | Nothing is stored, and "ask me later" was recorded less than an hour ago.                                                        |
| `.consentOk`       | `false`           | The stored choice needs nothing more, or a capping window is running on a choice that grants purpose 1.                          |
| `.configNotLoaded` | `true` or `false` | Provisional: the configuration had not loaded, so only GDPR applicability and the presence of a stored TC string were evaluated. |

***

## Shared Core Types

These types are shared with Android, and shown here in Kotlin, the language they are written in. Swift sees `Int` fields as `Int32`, `Long` as `Int64`, sets as `Set<KotlinInt>`, sealed-class cases as nested classes (`ConsentResult.Success`, `ConsentResult.Error`) and enum entries in lower camel case (`ConsentState.ready`, `UserActionResponse.askLater`).

### `ConsentResult`

```kotlin
sealed class ConsentResult {
    data class Success(val consentData: ConsentData) : ConsentResult()
    data class Error(val message: String) : ConsentResult()
}
```

### `InitResult`

```kotlin
sealed class InitResult {
    data object Success : InitResult()
    data class Error(val message: String, val code: Int = 0) : InitResult()
}
```

### `ConsentState`

```kotlin
enum class ConsentState {
    LOADING,      // Fetching remote config
    READY,        // Initialization finished, successfully or not: check getInitError()
    CONSENTING,   // Not set by the SDK in 2.0.0
    PERSISTING,   // Submitting consent
    COMPLETE      // Consent saved successfully
}
```

### `ConsentData`

```kotlin
data class ConsentData(
    val coreData: CoreData,              // TCF core consent fields
    val disclosedVendorsData: DisclosedVendorsData,
    val publisherTCData: PublisherTCData, // Publisher purposes
    val customData: CustomData,          // Sirdata + Google AC data
    val techData: TechData,              // Technical metadata
    var tcString: String,                // IAB TC String (encoded on the device)
    var sdString: String,                // SirData consent string
    var gppString: String                // GPP string
)
```

### `CoreData`

```kotlin
data class CoreData(
    val version: Int,
    var created: Long,
    var lastUpdated: Long,
    val cmpId: Int,
    val cmpVersion: Int,
    var consentScreen: Int,
    var consentLanguage: String,
    var vendorListVersion: Int,
    var tcfPolicyVersion: Int,
    var isServiceSpecific: Boolean,
    var useNonStandardTexts: Boolean,
    var selectedSpecialFeatureIds: Set<Int>,
    var selectedPurposeIds: Set<Int>,
    var selectedPurposeLIIds: Set<Int>,
    var purposeOneTreatment: Boolean,
    var publisherCC: String,
    var maxVendorId: Int,
    var selectedVendorIds: Set<Int>,
    var maxVendorIdLI: Int,
    var selectedVendorLIIds: Set<Int>,
    var publisherRestrictions: List<PublisherRestriction>
)
```

### `CustomData`

```kotlin
data class CustomData(
    var maxProviderId: Int,
    var selectedProviderIds: Set<Int>,           // Google AC providers
    var sirdataListVersion: Int,
    var maxSirdataVendorId: Int,
    var selectedSirdataVendorIds: Set<Int>,
    var maxSirdataVendorLIId: Int,
    var selectedSirdataVendorLIIds: Set<Int>,
    var selectedSirdataPurposeIds: Set<Int>,
    var selectedSirdataPurposeLIIds: Set<Int>
)
```

### `PublisherTCData`

```kotlin
data class PublisherTCData(
    var selectedStandardPurposeIds: Set<Int>,
    var selectedStandardPurposeLIIds: Set<Int>,
    var selectedCustomPurposeIds: Set<Int>,
    var selectedCustomPurposeLIIds: Set<Int>
)
```

### `UserActionResponse`

```kotlin
enum class UserActionResponse { ACCEPT, SAVE, REJECT, ASK_LATER }
```

`ASK_LATER` is reported to Sirdata as an "ask later" answer, but `submitConsent` still records the current selections, as for any other value. The consent UI never submits it: its "ask me later" button calls `recordAskLater()`, which records no consent.

### `SelectorStatus`

```kotlin
data class SelectorStatus(
    val dataId: Int,            // Purpose, vendor, or feature ID
    val isSelected: Boolean,   // true = consent, false = reject
    val ignoreRelated: Boolean = false  // Skip cascading to related items
)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cmp.docs.sirdata.net/en/mobile-apps-native-sdk/mobile-sdk/reference-1.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
