> For the complete documentation index, see [llms.txt](https://docs.growsurf.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.growsurf.com/developer-tools/ios-sdk/api-reference.md).

# API Reference

{% hint style="info" %}
If you're using an AI tool such as Cursor, ChatGPT Codex, or Claude Code to help you implement GrowSurf, we recommend utilizing our [MCP server](https://docs.growsurf.com/build-with-ai).
{% endhint %}

Use this page to look up individual GrowSurf iOS SDK methods. All SDK methods use Swift concurrency unless otherwise noted.

{% hint style="warning" %}
Use the Mobile SDK public key in your app. Do not embed your secret REST API key in an iOS app.
{% endhint %}

## SDK LIFECYCLE ↓

### Configure

Call this once before using GrowSurf. It connects the SDK to your GrowSurf campaign and Mobile SDK public key.

```swift
let growsurf = GrowSurf.configure(
    campaignId: "abc123",
    publicKey: "pk_mobile"
)
```

| Parameter        | Data Type | Description                                                                                  |
| ---------------- | --------- | -------------------------------------------------------------------------------------------- |
| **`campaignId`** | `String`  | (Required) Your GrowSurf program ID.                                                         |
| **`publicKey`**  | `String`  | (Required) Your Mobile SDK public key.                                                       |
| **`baseURL`**    | `URL`     | (Optional) Custom Mobile SDK API base URL. Defaults to `https://api.growsurf.com/mobile/v2`. |

Returns a configured `GrowSurf` instance.

#### **Example use**

```swift
import GrowSurfSDK

let growsurf = GrowSurf.configure(
    campaignId: "p9josq",
    publicKey: "pk_mobile"
)
```

Optionally, for advanced apps, initialize directly with explicit stores or a custom transport. Pass the production stores shown below, or your own conformances to the public store protocols:

```swift
let growsurf = GrowSurf(
    configuration: GrowSurfConfiguration(
        campaignId: "abc123",
        publicKey: "pk_mobile"
    ),
    tokenStore: GrowSurfKeychainTokenStore(),
    attributionStore: GrowSurfUserDefaultsAttributionStore(),
    mobileInstanceIdStore: GrowSurfUserDefaultsMobileInstanceIdStore()
)
```

***

### Set participant token

Use this after your backend creates a mobile participant token for a signed-in user. It lets participant-scoped SDK calls load or update that participant's data.

```swift
try await growsurf.setParticipantToken(participantToken)
```

| Parameter   | Data Type | Description                                                                                         |
| ----------- | --------- | --------------------------------------------------------------------------------------------------- |
| **`token`** | `String`  | (Required) A mobile participant token returned by your backend or by a participant creation method. |

Returns `Void`.

#### **Example use**

```swift
try await growsurf.setParticipantToken(participantToken)
```

{% hint style="info" %}
Use this method with tokens created by the REST API mobile participant token endpoint after a user is already signed in.
{% endhint %}

***

### Get participant token

Returns the participant token currently held by the SDK, or `nil` if none is stored. Useful right after the GrowSurf window's `ParticipantFields` signup flow so your app can persist the freshly minted token for the user's next session.

```swift
try await growsurf.participantToken()
```

Returns `String?`.

#### **Example use**

```swift
if let token = try await growsurf.participantToken() {
    // Persist the token to your backend so the user stays signed in to GrowSurf.
}
```

***

### Get current participant ID

Returns the current participant's ID decoded from the stored participant token, or `nil` if no participant token is set.

```swift
let participantId = try await growsurf.currentParticipantId()
```

Returns `String?`.

#### **Example use**

```swift
if let participantId = try await growsurf.currentParticipantId() {
    print("Current participant:", participantId)
}
```

***

### Get mobile instance ID

Returns the app-install ID the SDK sends with participant creation for mobile anti-fraud. You usually only need this if your backend creates mobile participant tokens and needs to pass the same ID to GrowSurf.

```swift
try await growsurf.mobileInstanceId()
```

Returns a lowercase UUID `String`.

#### **Example use**

```swift
let mobileInstanceId = try await growsurf.mobileInstanceId()
```

{% hint style="info" %}
Participant creation methods send `mobileInstanceId` automatically. Read it manually only when your backend creates a mobile participant token and needs to pass `mobileInstanceId` to the REST API.
{% endhint %}

***

### Shutdown

Call this when a user signs out or you need to reset GrowSurf state on the device. It clears the stored session token, participant token, and pending attribution.

```swift
try await growsurf.shutdown()
```

Returns `Void`.

#### **Example use**

```swift
try await growsurf.shutdown()
```

***

## CAMPAIGNS ↓

### Get campaign

Use this to read campaign details and rewards for the configured GrowSurf program. The SDK creates or uses a session token before calling GrowSurf.

```swift
try await growsurf.getCampaign()
```

Returns `GrowSurfCampaign`.

#### **Example use**

```swift
let campaign = try await growsurf.getCampaign()
print(campaign.id)
print(campaign.rewards)
```

***

### Get leaderboard

Use this to show leaderboard rows in a custom referral screen. You can page through results with page or cursor parameters.

```swift
try await growsurf.getLeaderboard(
    limit: 20,
    page: 1,
    offsetKey: nil,
    leaderboardType: nil
)
```

| Parameter             | Data Type | Description                                        |
| --------------------- | --------- | -------------------------------------------------- |
| **`limit`**           | `Int?`    | (Optional) Number of rows to return.               |
| **`page`**            | `Int?`    | (Optional) Page number.                            |
| **`offsetKey`**       | `String?` | (Optional) Cursor key for offset-based pagination. |
| **`leaderboardType`** | `String?` | (Optional) Leaderboard type filter.                |

Returns `GrowSurfLeaderboardResponse`.

#### **Example use**

```swift
let leaderboard = try await growsurf.getLeaderboard(limit: 10)
for row in leaderboard.participants {
    print(row.rank as Any, row.email as Any)
}
```

***

## GROWSURF WINDOW ↓

### Present GrowSurf window

Call this from your own button, menu item, or referral screen to open GrowSurf's native SwiftUI referral window.

{% hint style="info" %}
The native GrowSurf window uses the GrowSurf window settings from your dashboard. This method is available on iOS.
{% endhint %}

```swift
growsurf.presentGrowSurfWindow(
    from: viewController,
    identity: .existingParticipantToken(participantToken),
    theme: GrowSurfWindowTheme(),
    callbacks: GrowSurfWindowCallbacks()
)
```

| Parameter       | Data Type                 | Description                                                                                                                                                          |
| --------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`from`**      | `UIViewController`        | (Required) The view controller that presents the native window.                                                                                                      |
| **`identity`**  | `GrowSurfWindowIdentity`  | (Optional) How the window should identify the current user. Defaults to `.anonymous`.                                                                                |
| **`theme`**     | `GrowSurfWindowTheme`     | (Optional) Native presentation and theme overrides.                                                                                                                  |
| **`callbacks`** | `GrowSurfWindowCallbacks` | (Optional) Event callbacks for window open, close, participant creation (from the signup form), share tracking, invite sending, payout/settings actions, and errors. |

Returns `GrowSurfWindowController` — call `close()` on it to dismiss the window programmatically.

#### **Example use**

```swift
let windowController = growsurf.presentGrowSurfWindow(
    from: self,
    identity: .existingParticipantToken(participantToken),
    theme: GrowSurfWindowTheme(
        primaryColorHex: "#13795B",
        presentationStyle: .automatic
    ),
    callbacks: GrowSurfWindowCallbacks(
        onShareTracked: { type in
            print("Share tracked:", type)
        },
        onParticipantCreated: { participant, participantToken in
            print("Participant:", participant.id)
        },
        onError: { error in
            print("GrowSurf window error:", error)
        }
    )
)
```

***

### Get GrowSurf window

Use this when you are building your own referral screen instead of showing the native GrowSurf window. It returns the campaign, participant, share, reward, leaderboard, and affiliate data used by the window.

```swift
try await growsurf.getGrowSurfWindow(identity: .anonymous)
```

| Parameter      | Data Type                | Description                                           |
| -------------- | ------------------------ | ----------------------------------------------------- |
| **`identity`** | `GrowSurfWindowIdentity` | (Optional) Window identity. Defaults to `.anonymous`. |

Returns `GrowSurfWindowResponse`.

#### **Example use**

```swift
let window = try await growsurf.getGrowSurfWindow(
    identity: .existingParticipantToken(participantToken)
)

let shareUrl = window.participant?.shareUrl ?? window.share?.preferredUrl ?? window.share?.fallbackUrl
```

{% hint style="info" %}
Use `participant.shareUrl` as the customer-facing referral link when a participant is available. Fall back to `share.preferredUrl` or `share.fallbackUrl` only for rendering.
{% endhint %}

***

## ATTRIBUTION ↓

### Handle deep link

Call this when your app opens from a referral deep link. If the URL contains `grsf`, `ref`, or `referredBy`, the SDK saves the attribution so you can apply it when the user signs up.

```swift
try await growsurf.handleDeepLink(url)
```

| Parameter | Data Type | Description                                      |
| --------- | --------- | ------------------------------------------------ |
| **`url`** | `URL`     | (Required) The deep link URL opened by your app. |

Returns `GrowSurfAttribution?`. Returns `nil` when no GrowSurf referral value is found.

#### **Example use**

```swift
if let url {
    let attribution = try await growsurf.handleDeepLink(url)
    print(attribution?.referredBy as Any)
}
```

***

### Handle attribution parameters

Call this from an attribution provider callback, such as Branch, Adjust, AppsFlyer, or Singular. If the parameters include `grsf`, `ref`, or `referredBy` directly or inside URL-like values, the SDK saves the attribution for signup.

```swift
try await growsurf.handleAttributionParameters(parameters, provider: "branch")
```

| Parameter        | Data Type          | Description                                                                                                                                     |
| ---------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **`parameters`** | `[String: String]` | (Required) Provider callback parameters. The SDK recognizes direct values and nested URL-like values containing `grsf`, `ref`, or `referredBy`. |
| **`provider`**   | `String?`          | (Optional) Attribution provider name, such as `branch`, `adjust`, `appsflyer`, or `singular`.                                                   |

Returns `GrowSurfAttribution?`. Returns `nil` when no GrowSurf referral value is found.

#### **Example use**

```swift
let attribution = try await growsurf.handleAttributionParameters(
    [
        "grsf": "referrer_id",
        "click_id": "click_123",
        "unique": "true",
    ],
    provider: "branch"
)
```

***

### Get pending attribution

Use this to inspect referral attribution saved on this device before creating or signing in a participant.

```swift
try await growsurf.pendingAttribution()
```

Returns `GrowSurfAttribution?`.

#### **Example use**

```swift
if let attribution = try await growsurf.pendingAttribution() {
    print("Pending referrer:", attribution.referredBy as Any)
}
```

***

### Clear pending attribution

Clear saved referral attribution when it should no longer apply, such as after you handle it or when a different user signs in.

```swift
try await growsurf.clearPendingAttribution()
```

Returns `Void`.

#### **Example use**

```swift
try await growsurf.clearPendingAttribution()
```

***

### Validate referrer

Use this to check whether a saved or supplied referrer is valid before you show a referred state or create a participant.

```swift
try await growsurf.validateReferrer(attribution)
```

| Parameter         | Data Type              | Description                                                                                           |
| ----------------- | ---------------------- | ----------------------------------------------------------------------------------------------------- |
| **`attribution`** | `GrowSurfAttribution?` | (Optional) Attribution to validate. If omitted, the SDK validates locally stored pending attribution. |

Returns `GrowSurfValidateReferrerResponse`.

#### **Example use**

{% tabs %}
{% tab title="Pending attribution" %}

```swift
let validation = try await growsurf.validateReferrer()

if validation.valid {
    print("Valid referrer:", validation.referredBy as Any)
}
```

{% endtab %}

{% tab title="Explicit referrer" %}

```swift
let validation = try await growsurf.validateReferrer(referredBy: "referrer_id")

if validation.valid {
    print("Valid referrer")
}
```

{% endtab %}
{% endtabs %}

***

## PARTICIPANTS ↓

### Add referred participant

Use this for referred signups. The SDK looks for a saved or explicit referrer, validates it, and only creates the participant when the referral is valid.

```swift
try await growsurf.addReferredParticipant(input)
```

| Parameter   | Data Type                  | Description                                                                                                 |
| ----------- | -------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **`input`** | `GrowSurfParticipantInput` | (Required) Participant fields, optional explicit `referredBy`, optional attribution, and optional metadata. |

Returns `GrowSurfAddReferredParticipantResponse`.

#### **Example use**

```swift
let result = try await growsurf.addReferredParticipant(
    GrowSurfParticipantInput(
        email: "person@example.com",
        firstName: "Ada",
        lastName: "Lovelace",
        metadata: ["plan": "pro"]
    )
)

if result.added {
    print("Referred participant:", result.participant?.id as Any)
} else {
    print("Not added:", result.notAddedReason as Any)
}
```

{% hint style="info" %}
If no participant is added, `notAddedReason` will be `no_referrer`, `invalid_referrer`, or `participant_already_exists`.
{% endhint %}

***

### Add participant

Use this for public signup flows where the SDK can create a participant even without a referral. It sends pending attribution when available, stores the returned participant token when present, and includes the SDK-generated mobile instance ID for anti-fraud.

```swift
try await growsurf.addParticipant(input)
```

| Parameter   | Data Type                  | Description                                                                 |
| ----------- | -------------------------- | --------------------------------------------------------------------------- |
| **`input`** | `GrowSurfParticipantInput` | (Required) Participant fields, optional attribution, and optional metadata. |

Returns `GrowSurfCreateParticipantResponse`.

#### **Example use**

```swift
let response = try await growsurf.addParticipant(
    GrowSurfParticipantInput(
        email: "person@example.com",
        firstName: "Ada",
        lastName: "Lovelace",
        metadata: ["plan": "pro"]
    )
)

if let participant = response.participant {
    print("Created participant:", participant.id)
}
```

{% hint style="info" %}
Use this method for public signup flows where the SDK should create a new participant. If the email already belongs to an existing participant, GrowSurf returns `requiresParticipantToken: true` and does not return a participant token. For signed-in or existing users, use an SDK-issued participant token you already have, or create a mobile participant token from your backend, then pass it to `setParticipantToken(_:)` or `.existingParticipantToken(...)`.
{% endhint %}

***

### Get participant

Use this after you have a participant token to load the participant's referral data, including their referral link and counts.

```swift
try await growsurf.getParticipant()
```

Returns `GrowSurfParticipant`.

#### **Example use**

```swift
let participant = try await growsurf.getParticipant()
print(participant.shareUrl as Any)
```

***

### Update participant

Use this when your app lets a participant update profile fields, such as first name, last name, or metadata.

```swift
try await growsurf.updateParticipant(with: input)
```

| Parameter  | Data Type                        | Description                                                                   |
| ---------- | -------------------------------- | ----------------------------------------------------------------------------- |
| **`with`** | `GrowSurfParticipantUpdateInput` | (Required) Fields to update, such as `firstName`, `lastName`, and `metadata`. |

Returns `GrowSurfParticipant`.

#### **Example use**

```swift
let participant = try await growsurf.updateParticipant(
    with: GrowSurfParticipantUpdateInput(
        firstName: "Ada",
        lastName: "Lovelace",
        metadata: ["plan": "enterprise"]
    )
)
```

***

### Update vanity links

Use this when your app lets a participant manage multiple custom referral link keys at once.

```swift
try await growsurf.updateVanityLinks(vanityKeys: ["ada", "ada-pro"])
```

| Parameter        | Data Type  | Description                                               |
| ---------------- | ---------- | --------------------------------------------------------- |
| **`vanityKeys`** | `[String]` | (Required) Vanity keys to associate with the participant. |

Returns `GrowSurfParticipant`.

#### **Example use**

```swift
let participant = try await growsurf.updateVanityLinks(
    vanityKeys: ["ada", "ada-pro"]
)
```

***

## REFERRALS AND INVITES ↓

### Get participant referrals

Use this to show who a participant has referred and the status of each referral.

```swift
try await growsurf.getParticipantReferrals(
    limit: 20,
    offset: 0
)
```

| Parameter    | Data Type | Description                               |
| ------------ | --------- | ----------------------------------------- |
| **`limit`**  | `Int?`    | (Optional) Number of referrals to return. |
| **`offset`** | `Int?`    | (Optional) Offset for pagination.         |

Returns `GrowSurfReferralsResponse`.

#### **Example use**

```swift
let response = try await growsurf.getParticipantReferrals(
    limit: 20
)

for referral in response.referrals {
    print(referral.email as Any, referral.referralStatus as Any)
}
```

***

### Send invites

Use this to send referral invite emails from a participant's referral screen.

```swift
try await growsurf.sendInvites(
    emailAddresses: ["friend@example.com"],
    messageText: "Join me on GrowSurf",
    subjectText: "You're invited"
)
```

| Parameter            | Data Type  | Description                           |
| -------------------- | ---------- | ------------------------------------- |
| **`emailAddresses`** | `[String]` | (Required) Email addresses to invite. |
| **`messageText`**    | `String`   | (Required) Invite message body.       |
| **`subjectText`**    | `String?`  | (Optional) Invite email subject.      |

Returns `GrowSurfInviteResponse`.

#### **Example use**

```swift
let response = try await growsurf.sendInvites(
    emailAddresses: ["friend@example.com"],
    messageText: "Try this app with my referral link.",
    subjectText: "Join me"
)
```

***

### Track share

Call this after a participant shares their referral link from your UI. GrowSurf records the share type, such as `copy`, `email`, `sms`, or a social channel.

```swift
try await growsurf.trackShare(type: "copy")
```

| Parameter  | Data Type | Description                                                                                                               |
| ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------- |
| **`type`** | `String`  | (Required) Share type, such as `copy`, `email`, `sms`, or a social channel type returned by the GrowSurf window response. |

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
try await growsurf.trackShare(type: "copy")
```

***

## REFERRAL PROGRAMS ↓

### Trigger referral

<mark style="color:orange;">Referral programs only</mark>

Use this when a referred participant completes the in-app action that should count as a referral conversion. For purchases or other high-trust events, trigger referral credit from your backend instead.

```swift
try await growsurf.triggerReferral()
```

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
let response = try await growsurf.triggerReferral()
```

{% hint style="warning" %}
For server-verified purchases, subscriptions, or other high-trust reward events, trigger referral credit from your backend using the REST API or a GrowSurf integration instead of from the app.
{% endhint %}

***

### Get participant rewards

<mark style="color:orange;">Referral programs only</mark>

Use this to show the rewards a participant has earned or can track inside your app.

```swift
try await growsurf.getParticipantRewards(
    limit: 20,
    nextId: nil
)
```

| Parameter    | Data Type | Description                             |
| ------------ | --------- | --------------------------------------- |
| **`limit`**  | `Int?`    | (Optional) Number of rewards to return. |
| **`nextId`** | `String?` | (Optional) Cursor ID for the next page. |

Returns `GrowSurfRewardsResponse`.

#### **Example use**

```swift
let rewards = try await growsurf.getParticipantRewards(
    limit: 20
)
```

***

### Mark participant rewards read

<mark style="color:orange;">Referral programs only</mark>

Call this after showing reward notifications so GrowSurf can clear the participant's unread reward state.

```swift
try await growsurf.markParticipantRewardsRead()
```

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
try await growsurf.markParticipantRewardsRead()
```

***

### Get participant referral summary

<mark style="color:orange;">Referral programs only</mark>

Use this for referral programs to show a participant's high-level referral stats (referrals, leads, expired referrals, clicks, rewards earned, pending rewards, invites sent).

```swift
try await growsurf.getParticipantReferralSummary()
```

Returns `GrowSurfReferralSummary`.

#### **Example use**

```swift
let summary = try await growsurf.getParticipantReferralSummary()
print(summary.referrals as Any)
```

***

## AFFILIATE PROGRAMS ↓

### Get participant commissions

<mark style="color:orange;">Affiliate programs only</mark>

Use this for affiliate programs to show a participant's commission history.

```swift
try await growsurf.getParticipantCommissions(
    limit: 20,
    nextId: nil
)
```

| Parameter    | Data Type | Description                                 |
| ------------ | --------- | ------------------------------------------- |
| **`limit`**  | `Int?`    | (Optional) Number of commissions to return. |
| **`nextId`** | `String?` | (Optional) Cursor ID for the next page.     |

Returns `GrowSurfCommissionsResponse`.

#### **Example use**

```swift
let commissions = try await growsurf.getParticipantCommissions(
    limit: 20
)
```

***

### Mark participant commissions read

<mark style="color:orange;">Affiliate programs only</mark>

Call this after showing commission notifications so GrowSurf can clear the participant's unread commission state.

```swift
try await growsurf.markParticipantCommissionsRead()
```

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
try await growsurf.markParticipantCommissionsRead()
```

***

### Get participant payouts

<mark style="color:orange;">Affiliate programs only</mark>

Use this for affiliate programs to show a participant's payout history.

```swift
try await growsurf.getParticipantPayouts(
    limit: 20,
    nextId: nil
)
```

| Parameter    | Data Type | Description                             |
| ------------ | --------- | --------------------------------------- |
| **`limit`**  | `Int?`    | (Optional) Number of payouts to return. |
| **`nextId`** | `String?` | (Optional) Cursor ID for the next page. |

Returns `GrowSurfPayoutsResponse`.

#### **Example use**

```swift
let payouts = try await growsurf.getParticipantPayouts(
    limit: 20
)
```

***

### Mark participant payouts read

<mark style="color:orange;">Affiliate programs only</mark>

Call this after showing payout notifications so GrowSurf can clear the participant's unread payout state.

```swift
try await growsurf.markParticipantPayoutsRead()
```

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
try await growsurf.markParticipantPayoutsRead()
```

***

### Get participant affiliate summary

<mark style="color:orange;">Affiliate programs only</mark>

Use this for affiliate programs to show a participant's high-level affiliate stats, such as referral revenue, total paid out, and upcoming payout.

```swift
try await growsurf.getParticipantAffiliateSummary()
```

Returns `GrowSurfAffiliateSummary`.

#### **Example use**

```swift
let summary = try await growsurf.getParticipantAffiliateSummary()
print(summary.upcomingPayout as Any)
```

***

### Request PayPal confirm email

<mark style="color:orange;">Affiliate programs only</mark>

Use this when your affiliate program needs the participant to confirm their PayPal email before payouts can continue.

```swift
try await growsurf.requestPaypalConfirmEmail()
```

Returns `GrowSurfSuccessResponse`.

#### **Example use**

```swift
let response = try await growsurf.requestPaypalConfirmEmail()
```

***

### Request tax info session

Use this when the campaign requires tax documentation and the participant needs to complete or resubmit their W-9 / W-8 form before rewards or payouts can continue. It starts a secure hosted tax-form session and returns the hosted URL to open in an in-app browser, plus the participant's new tax status. The native GrowSurf window calls this automatically from its Tax Forms settings row; call it yourself only if you build a custom settings UI.

```swift
try await growsurf.requestTaxInfoSession()
```

Returns `GrowSurfTaxSessionResponse`.

#### **Example use**

```swift
let session = try await growsurf.requestTaxInfoSession()
if let urlString = session.hostedUrl, let url = URL(string: urlString) {
    await UIApplication.shared.open(url)
}
```

{% hint style="info" %}
GrowSurf never stores participant tax IDs. The W-9 / W-8 is completed on a hosted page served by GrowSurf's IRS-authorized e-file partner.
{% endhint %}

***

## ATTRIBUTION ADAPTERS ↓

### Branch attribution adapter

Use this helper when Branch returns attribution data. It normalizes Branch payloads and can store the resulting GrowSurf attribution on the SDK.

```swift
GrowSurfBranchAttribution.normalize(parameters)
try await GrowSurfBranchAttribution.handle(parameters, sdk: growsurf)
```

| Method                                               | Description                                                                       |
| ---------------------------------------------------- | --------------------------------------------------------------------------------- |
| **`normalize(_ parameters: [String: String])`**      | Parses a string dictionary and returns `GrowSurfAttribution?` without storing it. |
| **`normalize(_ parameters: [String: Any])`**         | Converts a mixed dictionary, then parses attribution without storing it.          |
| **`normalize(_ parameters: [AnyHashable: Any])`**    | Converts a hashable-key dictionary, then parses attribution without storing it.   |
| **`handle(_ parameters: [String: String], sdk:)`**   | Parses and stores attribution on the provided SDK instance.                       |
| **`handle(_ parameters: [String: Any], sdk:)`**      | Converts, parses, and stores attribution on the provided SDK instance.            |
| **`handle(_ parameters: [AnyHashable: Any], sdk:)`** | Converts, parses, and stores attribution on the provided SDK instance.            |

#### **Example use**

```swift
import GrowSurfBranchAttribution

try await GrowSurfBranchAttribution.handle(
    branchParams,
    sdk: growsurf
)
```

***

### Adjust attribution adapter

Use this helper when Adjust returns a deep link. It normalizes the URL and can store the resulting GrowSurf attribution on the SDK.

```swift
GrowSurfAdjustAttribution.normalize(url)
try await GrowSurfAdjustAttribution.handle(url, sdk: growsurf)
```

| Method                                  | Description                                                         |
| --------------------------------------- | ------------------------------------------------------------------- |
| **`normalize(_ url: URL)`**             | Parses a URL and returns `GrowSurfAttribution?` without storing it. |
| **`normalize(_ urlString: String)`**    | Parses a URL string or encoded URL string without storing it.       |
| **`handle(_ url: URL, sdk:)`**          | Parses and stores attribution on the provided SDK instance.         |
| **`handle(_ urlString: String, sdk:)`** | Parses and stores attribution on the provided SDK instance.         |

#### **Example use**

```swift
import GrowSurfAdjustAttribution

try await GrowSurfAdjustAttribution.handle(
    adjustDeeplinkURL,
    sdk: growsurf
)
```

***

### AppsFlyer attribution adapter

Use this helper when AppsFlyer returns conversion or deep link data. It normalizes the payload and can store the resulting GrowSurf attribution on the SDK.

```swift
GrowSurfAppsFlyerAttribution.normalize(parameters)
try await GrowSurfAppsFlyerAttribution.handle(parameters, sdk: growsurf)
```

| Method                                               | Description                                                                       |
| ---------------------------------------------------- | --------------------------------------------------------------------------------- |
| **`normalize(_ parameters: [String: String])`**      | Parses a string dictionary and returns `GrowSurfAttribution?` without storing it. |
| **`normalize(_ parameters: [String: Any])`**         | Converts a mixed dictionary, then parses attribution without storing it.          |
| **`normalize(_ parameters: [AnyHashable: Any])`**    | Converts a hashable-key dictionary, then parses attribution without storing it.   |
| **`handle(_ parameters: [String: String], sdk:)`**   | Parses and stores attribution on the provided SDK instance.                       |
| **`handle(_ parameters: [String: Any], sdk:)`**      | Converts, parses, and stores attribution on the provided SDK instance.            |
| **`handle(_ parameters: [AnyHashable: Any], sdk:)`** | Converts, parses, and stores attribution on the provided SDK instance.            |

#### **Example use**

```swift
import GrowSurfAppsFlyerAttribution

try await GrowSurfAppsFlyerAttribution.handle(
    conversionData,
    sdk: growsurf
)
```

***

### Singular attribution adapter

Use this helper when Singular returns callback parameters or deep link values. It normalizes the payload and can store the resulting GrowSurf attribution on the SDK.

```swift
GrowSurfSingularAttribution.normalize(parameters)
try await GrowSurfSingularAttribution.handle(parameters, sdk: growsurf)
```

| Method                                               | Description                                                                       |
| ---------------------------------------------------- | --------------------------------------------------------------------------------- |
| **`normalize(_ parameters: [String: String])`**      | Parses a string dictionary and returns `GrowSurfAttribution?` without storing it. |
| **`normalize(_ parameters: [String: Any])`**         | Converts a mixed dictionary, then parses attribution without storing it.          |
| **`normalize(_ parameters: [AnyHashable: Any])`**    | Converts a hashable-key dictionary, then parses attribution without storing it.   |
| **`normalize(_ url: URL)`**                          | Parses a URL without storing it.                                                  |
| **`normalize(_ urlString: String)`**                 | Parses a URL string or encoded URL string without storing it.                     |
| **`handle(_ parameters: [String: String], sdk:)`**   | Parses and stores attribution on the provided SDK instance.                       |
| **`handle(_ parameters: [String: Any], sdk:)`**      | Converts, parses, and stores attribution on the provided SDK instance.            |
| **`handle(_ parameters: [AnyHashable: Any], sdk:)`** | Converts, parses, and stores attribution on the provided SDK instance.            |
| **`handle(_ url: URL, sdk:)`**                       | Parses and stores attribution on the provided SDK instance.                       |
| **`handle(_ urlString: String, sdk:)`**              | Parses and stores attribution on the provided SDK instance.                       |

#### **Example use**

```swift
import GrowSurfSingularAttribution

try await GrowSurfSingularAttribution.handle(
    singularPayload,
    sdk: growsurf
)
```

***

## UTILITIES ↓

### Normalize attribution parameters

Use this when you need to read GrowSurf attribution from raw provider parameters without storing it. It looks for `grsf`, `ref`, or `referredBy` directly and inside URL-like values.

```swift
GrowSurfAttributionNormalizer.normalize(
    parameters: parameters,
    provider: "branch"
)
```

| Parameter        | Data Type          | Description                                                                                |
| ---------------- | ------------------ | ------------------------------------------------------------------------------------------ |
| **`parameters`** | `[String: String]` | (Required) Raw parameters. The normalizer checks direct fields and URL-like nested values. |
| **`provider`**   | `String?`          | (Optional) Provider name to attach to the attribution result.                              |

Returns `GrowSurfAttribution?`.

#### **Example use**

```swift
let attribution = GrowSurfAttributionNormalizer.normalize(
    parameters: [
        "deep_link_value": "https://example.com/signup?grsf=referrer_id",
        "click_id": "click_123",
    ],
    provider: "appsflyer"
)
```

***

### Normalize attribution URL

Use this when you need to parse a URL for `grsf`, `ref`, or `referredBy` without storing attribution on the SDK.

```swift
GrowSurfAttributionNormalizer.normalize(url: url, provider: "adjust")
```

| Parameter      | Data Type | Description                                                   |
| -------------- | --------- | ------------------------------------------------------------- |
| **`url`**      | `URL`     | (Required) URL to parse.                                      |
| **`provider`** | `String?` | (Optional) Provider name to attach to the attribution result. |

Returns `GrowSurfAttribution?`.

#### **Example use**

```swift
let attribution = GrowSurfAttributionNormalizer.normalize(
    url: URL(string: "https://example.com/signup?grsf=referrer_id")!,
    provider: "adjust"
)
```

***

### Convert attribution parameters to strings

Use this before passing mixed provider callback payloads to the normalizer or SDK attribution methods. It converts nested values into a `[String: String]` dictionary without storing attribution.

```swift
GrowSurfAttributionNormalizer.stringParameters(from: parameters)
```

| Parameter        | Data Type       | Description                                                                                            |
| ---------------- | --------------- | ------------------------------------------------------------------------------------------------------ |
| **`parameters`** | `[String: Any]` | (Required) Provider callback payload. Nested dictionaries and arrays are flattened into string values. |

Returns `[String: String]`.

#### **Example use**

```swift
let stringParameters = GrowSurfAttributionNormalizer.stringParameters(
    from: providerPayload
)

try await growsurf.handleAttributionParameters(
    stringParameters,
    provider: "branch"
)
```


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.growsurf.com/developer-tools/ios-sdk/api-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
