Plaid logo
Docs
ALL DOCS

Link

  • Overview
Platforms
  • Web
  • iOS
  • Android
  • React Native
  • Hosted Link
Core Link functionality
  • OAuth guide
  • Update mode
  • Preventing duplicate Items
  • Data Transparency Messaging migration
  • Returning user experience
Additional Link modes
  • Embedded Link
  • Multi-Item Link
  • Link Recovery (beta)
Optimizing Link
  • Link analytics and tracking
  • Optimizing Link conversion
  • Pre-Link messaging
  • Customizing Link
  • Choosing when to initialize products
Errors and troubleshooting
  • Troubleshooting
  • Handling an invalid Link Token
  • Institution status in Link
Legacy flows
  • Webview integrations
Plaid logo
Docs
Plaid.com
Log in
Get API Keys
Open nav
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about the Plaid API. Try asking questions like:
    Pssst -- I also moonlight as your IDE's research librarian! Plug me in via the Plaid AI coding toolkit.
    Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.

    Link iOS SDK

    Reference for integrating with the Link iOS SDK

    Overview

    The Plaid Link SDK is a quick and secure way to link bank accounts to Plaid from within your iOS app. LinkKit handles credential validation, multi-factor authentication, OAuth, and errors without passing sensitive information to your server.

    Prefer to learn by watching? Check out this quick guide to implementing Plaid on iOS devices

    Want even more video lessons? A full tutorial for integrating Plaid with iOS is available on our YouTube channel.

    To get started, sign up for free API keys and try the example apps.

    Initial iOS setup

    Before writing code using the SDK, register your app with Plaid and configure Universal Links for OAuth redirects.

    The "Register your redirect URI" and "Set up Universal Links" steps are required for OAuth. They can be skipped for Link flows that do not connect to financial institutions, such as Identity Verification or Document Income.

    Register your redirect URI
    1. Sign in to the Plaid Dashboard and go to Developers -> API.
    2. Next to Allowed redirect URIs, click Configure, then Add New URI.
    3. Enter your redirect URI, which must also be set up as a Universal Link for your application, for example: https://app.example.com/plaid/.
    4. Click Save Changes.

    These redirect URIs must be set up as Universal Links in your application. For details, see Apple's documentation on Allowing Apps and Websites to Link to Your Content.

    Plaid does not support registering URLs with custom URL schemes as redirect URIs. Universal Links use a two-way association between your app and website, which helps ensure your application is opened during OAuth.

    Set up Universal Links

    To return users to your application after a bank's OAuth flow, your redirect URI must be a Universal Link. An example redirect URI is https://app.example.com/plaid.

    Universal Links require:

    • An applinks entitlement for the Associated Domains capability in your app.
    • An apple-app-site-association file on your website.

    There are a few requirements for apple-app-site-association files:

    • Must be a static JSON file
    • Must be hosted using a https:// scheme with a valid certificate and no redirects
    • Must be hosted at https://<my-fully-qualified-domain>/.well-known/apple-app-site-association

    Below is an example for https://my-app.com:

    {
      "applinks": {
        "details": [
          {
            "appIDs": ["<My Application Identifier Prefix>.<My Bundle ID>"],
            "components": [
              {
                "/": "/plaid/*",
                "comment": "Matches any URL path whose path starts with /plaid/"
              }
            ]
          }
        ]
      }
    }

    Ensure that the corresponding entry for the configured redirect URI in the apple-app-site-association file on your website continues to be available. If it is removed, OAuth sessions will fail until it is available again.

    Installation

    Plaid Link for iOS is bundled with your application. For Swift integrations, we recommend using plaid-link-ios-spm with Swift Package Manager. Submitting a new version of your application with the updated LinkKit.xcframework is required to update LinkKit.

    Requirements
    LinkKit iOS versionXcode toolchain minimum supportSupported iOS versions
    LinkKit 7.x.xXcode 16.1iOS 15 or greater
    LinkKit 6.x.xXcode 16.1iOS 14 or greater
    Select group for content switcher
    Swift Package Manager
    1. To integrate LinkKit using Swift Package Manager, Swift version >= 5.3 is required.
    2. In your Xcode project from the Project Navigator (Xcode -> View -> Navigators -> Project Cmd 1) select your project, activate the Package Dependencies tab and click on the plus symbol + to open the Add Package popup window:
      Xcode interface showing how to add a Swift package dependency; plus button highlighted.
    3. Enter the LinkKit package URL https://github.com/plaid/plaid-link-ios-spm into the search bar in the top right corner of the Add Package popup window. The main repository with full git history is very large (~1 GB), and Swift Package Manager always downloads the full repository with all git history. This plaid-link-ios-spm repository is much smaller (less than 500kb), making the download faster.
    4. Select the plaid-link-ios-spm package.
    5. Choose your Dependency Rule (we recommend Up to Next Major Version).
    6. Select the project to which you would like to add LinkKit, then click Add Package:
      Xcode screenshot showing input of Plaid Link iOS Swift package URL for package addition. 'Add Package' button highlighted.
    7. Select the LinkKit package product and click Add Package:
      Dialog in Xcode for selecting Plaid link-ios package. 'LinkKit' checked, type 'Library', target 'MySampleApp'.
      Objective-C integrations should use the same `https://github.com/plaid/plaid-link-ios-spm` package, select the `LinkKitObjC` package product instead, and import it with `@import LinkKitObjC;`.
    8. Verify that the LinkKit Swift package was properly added as a package dependency to your project:
      Xcode showing the Plaid Link iOS package dependency from GitHub in Package Dependencies tab.
    9. Select your application target and ensure that the LinkKit library is embedded into your application:
      Xcode screenshot showing the Frameworks section with LinkKit listed under Package Dependencies for MySampleApp.
    CocoaPods

    CocoaPods is legacy-only. The last Plaid iOS SDK release that supports CocoaPods is 6.4.7. LinkKit 7 does not support CocoaPods. New integrations should use Swift Package Manager.

    If you are still on LinkKit 6.x, use:

    pod 'Plaid'

    Then run:

    pod install
    Manual

    Get the latest LinkKit.xcframework and embed it into your application target.

    Xcode project with LinkKit.xcframework added under Frameworks, Libraries, and Embedded Content. LinkKit.xcframework folder in Downloads.
    Camera Support (Identity Verification only)

    When using Identity Verification, add a NSCameraUsageDescription entry to your application's plist. iOS will crash your application if this string is not provided and Link needs camera access.

    Upgrading

    New versions of LinkKit are released frequently. We recommend updating at least once a quarter, and ideally once a month.

    SDK versions are supported for two years; with each major SDK release, Plaid will stop officially supporting any previous SDK versions that are more than two years old. While these older versions are expected to continue to work without disruption, Plaid will not provide assistance with unsupported SDK versions.

    LinkKit 7 moves Swift integrations from Handler-based APIs to session-based APIs. For migration details, see the LinkKit 7 migration guide.

    For details on each release, see the GitHub releases.

    Opening Link

    Before opening Link, create a new link_token on your server using /link/token/create.

    For iOS, /link/token/create must include the redirect_uri parameter and it must match the redirect URI you configured with Plaid.

    Standard Link

    Create a configuration, create a session, retain the session, and open it when the user is ready.

    Starting the Plaid Link for iOS experience begins with creating a link_token. Once the link_token is passed to your app, create an instance of LinkTokenConfiguration, then create a PlaidLinkSession using Plaid.createPlaidLinkSession(configuration:). Plaid will begin to pre-load Link as soon as the session is created, so to reduce UI latency, create the session when initializing the screen where the user can enter the Link flow.

    After creating the session, show Link by calling open(using:) with your preferred presentation method, or by presenting session.sheet() in SwiftUI.

    Note that each time you open Link, you will need to get a new link_token from your server and create a new LinkTokenConfiguration with it.

    create

    Properties

    token
    StringString

    Specify a link_token to authenticate your app with Link. This is a short lived, one-time use token that should be unique for each Link session. In addition to the primary flow, a link_token can be configured to launch Link in update mode. See the /link/token/create endpoint for more details.

    onSuccess
    closureclosure

    A required closure that is called when a user successfully links an Item. The closure should expect a single LinkSuccess argument, containing the publicToken String and a metadata of type SuccessMetadata. See onSuccess below.

    onExit
    closureclosure

    An optional closure that is called when a user exits Link without successfully linking an Item, or when an error occurs during Link initialization. The closure should expect a single LinkExit argument, containing an optional error and a metadata of type ExitMetadata. See onExit below.

    onEvent
    closureclosure

    An optional closure that is called when a user reaches certain points in the Link flow. The closure should expect a single LinkEvent argument, containing an eventName enum of type EventType and a metadata of type EventMetadata. See onEvent below.

    onLoad
    closureclosure

    An optional closure that is called when Link has finished loading and is ready to be presented.

    Select group for content switcher
    SwiftUI
    import LinkKit
    import SwiftUI
    
    struct ConnectBankView: View {
        let linkToken: String
        @State private var linkSession: PlaidLinkSession?
        @State private var isPresentingLink = false
        @State private var isReady = false
    
        var body: some View {
            Button("Connect account") {
                isPresentingLink = true
            }
            .disabled(!isReady)
            .onAppear(perform: createSession)
            .sheet(isPresented: $isPresentingLink) {
                linkSession?.sheet()
            }
        }
    
        private func createSession() {
            let configuration = LinkTokenConfiguration(
                token: linkToken,
                onSuccess: { success in
                    // Send success.publicToken to your app server.
                    isPresentingLink = false
                },
                onExit: { _ in
                    isPresentingLink = false
                },
                onEvent: { event in
                    // Optionally handle Link events.
                },
                onLoad: {
                    isReady = true
                }
            )
    
            do {
                linkSession = try Plaid.createPlaidLinkSession(configuration: configuration)
            } catch {
                // Handle the error.
            }
        }
    }
    UIKit
    import LinkKit
    import UIKit
    
    final class ConnectBankViewController: UIViewController {
        private var linkSession: PlaidLinkSession?
        private let linkToken: String = "<#LINK_TOKEN_FROM_SERVER#>"
    
        override func viewDidLoad() {
            super.viewDidLoad()
            createSession()
        }
    
        private func createSession() {
            let configuration = LinkTokenConfiguration(
                token: linkToken,
                onSuccess: { success in
                    // Send success.publicToken to your app server.
                },
                onExit: { exit in
                    // Optionally handle exit data.
                },
                onEvent: { event in
                    // Optionally handle Link events.
                },
                onLoad: { [weak self] in
                    // Enable your "Connect account" button.
                }
            )
    
            do {
                linkSession = try Plaid.createPlaidLinkSession(configuration: configuration)
            } catch {
                // Handle the error.
            }
        }
    
        @objc private func connectButtonTapped() {
            linkSession?.open(using: .viewController(self))
        }
    }
    Objective-C
    @import LinkKitObjC;
    
    @interface ConnectBankViewController ()
    @property (nonatomic, strong) id<PLKHandler> linkHandler;
    @end
    
    - (void)createLink {
        void (^onSuccess)(PLKLinkSuccess *) = ^(PLKLinkSuccess *success) {
            // Send success.publicToken to your app server.
        };
    
        PLKLinkTokenConfiguration *configuration =
          [[PLKLinkTokenConfiguration alloc] initWithToken:@"<#LINK_TOKEN_FROM_SERVER#>"
                                                 onSuccess:onSuccess];
    
        configuration.onExit = ^(PLKLinkExit *exit) {
            // Optionally handle exit data.
        };
    
        configuration.onEvent = ^(PLKLinkEvent *event) {
            // Optionally handle Link events.
        };
    
        NSError *error = nil;
        self.linkHandler = [PLKPlaid createWithLinkTokenConfiguration:configuration
                                                                error:&error];
        if (self.linkHandler == nil) {
            // Handle the error.
            return;
        }
    }
    
    - (void)connectButtonTapped {
        // Retain linkHandler for the duration of the Link flow.
        [self.linkHandler openWithContextViewController:self];
    }
    =*=*=*=

    onSuccess

    The closure is called when a user successfully links an Item. It should take a single LinkSuccess argument, containing the publicToken String and a metadata of type SuccessMetadata.

    onSuccess

    Properties

    linkSuccess
    LinkSuccessLinkSuccess

    Contains the publicToken and metadata for this successful flow.

    publicToken
    StringString

    Displayed once a user has successfully completed Link. If using Identity Verification or Beacon, this field will be null. If using Document Income or Payroll Income, the public_token will be returned, but is not used.

    metadata
    LinkSuccessLinkSuccess

    Displayed once a user has successfully completed Link.

    institution
    nullableInstitutionnullable, Institution

    An institution object. If the Item was created via Same-Day Micro-deposit verification, will be null.

    name
    StringString

    The full institution name, such as 'Wells Fargo'

    institutionID
    InstitutionID (String)InstitutionID (String)

    The Plaid institution identifier

    accounts
    Array<Account>Array<Account>

    A list of accounts attached to the connected Item

    id
    AccountID (String)AccountID (String)

    The Plaid account_id

    name
    StringString

    The official account name

    mask
    Optional<AccountMask> (Optional<String>)Optional<AccountMask> (Optional<String>)

    The last 2-4 alphanumeric characters of an account's official account number. Note that the mask may be non-unique between an Item's accounts, it may also not match the mask that the bank displays to the user.

    subtype
    AccountSubtypeAccountSubtype

    The account subtype and its type. See Account Types for a full list of possible values.

    verificationStatus
    Optional<VerificationStatus>Optional<VerificationStatus>

    Indicates an Item's micro-deposit-based verification or database verification status. Possible values are:

    pending_automatic_verification: The Item is pending automatic verification.

    pending_manual_verification: The Item is pending manual micro-deposit verification. Items remain in this state until the user successfully verifies the deposit.

    automatically_verified: The Item has successfully been automatically verified.

    manually_verified: The Item has successfully been manually verified.

    verification_expired: Plaid was unable to automatically verify the deposit within 7 calendar days and will no longer attempt to validate the Item. Users may retry by submitting their information again through Link.

    verification_failed: The Item failed manual micro-deposit verification because the user exhausted all 3 verification attempts. Users may retry by submitting their information again through Link.

    database_matched: The Item has successfully been verified using Plaid's data sources.

    database_insights_pending: The Database Insights result is pending and will be available upon Auth request.

    nil: Neither micro-deposit-based verification nor database verification are being used for the Item.

    linkSessionID
    StringString

    A unique identifier associated with a user's actions and events through the Link flow. Include this identifier when opening a support ticket for faster turnaround.

    metadataJSON
    StringString

    Unprocessed metadata, formatted as JSON, sent from the Plaid API.

    Select group for content switcher
    Swift
    let configuration = LinkTokenConfiguration(
        token: linkToken,
        onSuccess: { success in
            // Send success.publicToken to your app server.
        },
        onExit: nil,
        onEvent: nil,
        onLoad: nil
    )
    Objective-C
    void (^onSuccess)(PLKLinkSuccess *) = ^(PLKLinkSuccess *success) {
        // Send success.publicToken to your app server.
    };
    
    PLKLinkTokenConfiguration *configuration =
      [[PLKLinkTokenConfiguration alloc] initWithToken:@"<#LINK_TOKEN_FROM_SERVER#>"
                                             onSuccess:onSuccess];
    =*=*=*=

    onExit

    This optional closure is called when a user exits Link without successfully linking an Item, or when an error occurs during Link initialization. It should take a single LinkExit argument, containing an optional error and a metadata of type ExitMetadata.

    onExit

    Properties

    linkExit
    LinkExitLinkExit

    Contains the optional error and metadata for when the flow was exited.

    error
    Optional<ExitError> (Swift), Optional<NSError> (Objective-C)Optional<ExitError> (Swift), Optional<NSError> (Objective-C)

    An Error type that contains the errorCode, errorMessage, and displayMessage of the error that was last encountered by the user. If no error was encountered, error will be nil. In Objective-C, field names will match the NSError type.

    errorCode
    ExitErrorCodeExitErrorCode

    The error code and error type that the user encountered. Each errorCode has an associated errorType, which is a broad categorization of the error.

    errorMessage
    StringString

    A developer-friendly representation of the error code.

    displayMessage
    Optional<String>Optional<String>

    A user-friendly representation of the error code or nil if the error is not related to user action. This may change over time and is not safe for programmatic use.

    metadata
    ExitMetadataExitMetadata

    Displayed if a user exits Link without successfully linking an Item.

    status
    Optional<ExitStatus>Optional<ExitStatus>

    The status key indicates the point at which the user exited the Link flow.

    requiresQuestions

    User prompted to answer security question(s).

    requiresSelections

    User prompted to answer multiple choice question(s).

    requiresCode

    User prompted to provide a one-time passcode.

    chooseDevice

    User prompted to select a device on which to receive a one-time passcode.

    requiresCredentials

    User prompted to provide credentials for the selected financial institution or has not yet selected a financial institution.

    requiresAccountSelection

    User prompted to select one or more financial accounts to share

    institutionNotFound

    User exited the Link flow on the institution selection pane. Typically this occurs after the user unsuccessfully (no results returned) searched for a financial institution. Note that this status does not necessarily indicate that the user was unable to find their institution, as it is used for all user exits that occur from the institution selection pane, regardless of other user behavior.

    institutionNotSupported

    User exited the Link flow after discovering their selected institution is no longer supported by Plaid

    unknown

    The exit status has not been defined in the current version of the SDK. The unknown case has an associated value carrying the original exit status as sent by the Plaid API.

    institution
    Optional<Institution>Optional<Institution>

    An institution object. If the Item was created via Same-Day Micro-deposit verification, will be omitted.

    institutionID
    InstitutionID (String)InstitutionID (String)

    The Plaid specific identifier for the institution.

    name
    StringString

    The full institution name, such as 'Wells Fargo'.

    linkSessionID
    Optional<String>Optional<String>

    A unique identifier associated with a user's actions and events through the Link flow. Include this identifier when opening a support ticket for faster turnaround.

    requestID
    Optional<String>Optional<String>

    The request ID for the last request made by Link. This can be shared with Plaid Support to expedite investigation.

    metadataJSON
    RawJSONMetadata (String)RawJSONMetadata (String)

    Unprocessed metadata, formatted as JSON, sent from Plaid API.

    Select group for content switcher
    Swift
    let configuration = LinkTokenConfiguration(
        token: linkToken,
        onSuccess: { success in
            // Send success.publicToken to your app server.
        },
        onExit: { exit in
            if let error = exit.error {
                // Handle error.errorCode, error.errorMessage, and error.displayMessage.
            }
    
            // Use exit.metadata for support and analytics.
        },
        onEvent: nil,
        onLoad: nil
    )
    Objective-C
    configuration.onExit = ^(PLKLinkExit *exit) {
        // Optionally handle exit.error and exit.metadata.
    };
    =*=*=*=

    onEvent

    This closure is called when certain events in the Plaid Link flow have occurred. The open, layerReady, layerNotAvailable, layerAutofillNotAvailable events are guaranteed to fire in real time; other events will typically be fired when the Link session finishes, when onSuccess or onExit is called. Callback ordering is not guaranteed; onEvent callbacks may fire before, after, or surrounding the onSuccess or onExit callback, and event callbacks are not guaranteed to fire in the order in which they occurred.

    The following onEvent callbacks are stable, which means that they are suitable for programmatic use in your application's logic: open, exit, handoff, selectInstitution, error, bankIncomeInsightsCompleted, identityVerificationPassSession, identityVerificationFailSession, layerReady, layerNotAvailable, layerAutofillNotAvailable. The remaining callback events are informational and subject to change, and should be used for analytics and troubleshooting purposes only.

    onEvent

    Properties

    linkEvent
    LinkEventLinkEvent

    Contains the eventName and metadata for the Link event.

    eventName
    EventNameEventName

    An enum representing the event that has just occurred in the Link flow.

    autoSubmitPhone

    The user was automatically sent an OTP code without a UI prompt. This event can only occur if the user's phone number was provided to Link via the /link/token/create call and the user has previously consented to receive OTP codes from Plaid.

    bankIncomeInsightsCompleted

    The user has completed the Assets and Bank Income Insights flow.

    closeOAuth

    The user closed the third-party website or mobile app without completing the OAuth flow.

    connectNewInstitution

    The user has chosen to link a new institution instead of linking a saved institution. This event is only emitted in the Link Remember Me flow.

    error

    A recoverable error occurred in the Link flow, see the errorCode in the metadata.

    exit

    The user has exited without completing the Link flow and the onExit callback is fired.

    failOAuth

    The user encountered an error while completing the third-party's OAuth login flow.

    handoff

    The user has exited Link after successfully linking an Item.

    identityMatchFailed

    An Identity Match check configured via the Account Verification Dashboard failed the Identity Match rules and did not detect a match.

    identityMatchPassed

    An Identity Match check configured via the Account Verification Dashboard passed the Identity Match rules and detected a match.

    identityVerificationStartStep

    The user has started a step of the Identity Verification flow. The step is indicated by view_name.

    identityVerificationPassStep

    The user has passed a step of the Identity Verification flow. The step is indicated by view_name.

    identityVerificationFailStep

    The user has failed a step of the Identity Verification flow. The step is indicated by view_name.

    identityVerificationPendingReviewStep

    The user has reached the pending review state.

    identityVerificationCreateSession

    The user has started a new Identity Verification session.

    identityVerificationResumeSession

    The user has resumed an existing Identity Verification session.

    identityVerificationPassSession

    The user has passed their Identity Verification session.

    identityVerificationFailSession

    The user has failed their Identity Verification session.

    identityVerificationPendingReviewSession

    The user has completed their Identity Verification session, which is now in a pending review state.

    identityVerificationOpenUI

    The user has opened the UI of their Identity Verification session.

    identityVerificationResumeUI

    The user has resumed the UI of their Identity Verification session.

    identityVerificationCloseUI

    The user has closed the UI of their Identity Verification session.

    layerAutofillNotAvailable

    The user's date of birth passed to Link is not eligible for Layer Extended Autofill.

    layerNotAvailable

    The user phone number passed to Link is not eligible for Layer.

    layerReady

    The user phone number passed to Link is eligible for Layer and open() may now be called.

    matchedSelectInstitution

    The user selected an institution that was presented as a matched institution. This event can be emitted if Embedded Institution Search is being used, if the institution was surfaced as a matched institution likely to have been linked to Plaid by a returning user, or if the institution's routing_number was provided when calling /link/token/create. For details on which scenario is triggering the event, see metadata.matchReason.

    open

    The user has opened Link.

    openMyPlaid

    The user has opened my.plaid.com. This event is only sent when Link is initialized with Assets as a product.

    openOAuth

    The user has navigated to a third-party website or mobile app in order to complete the OAuth login flow.

    searchInstitution

    The user has searched for an institution.

    selectAuthType

    The user has chosen whether to Link instantly or manually (i.e., with micro-deposits). This event emits the selection metadata to indicate the user's selection.

    selectBrand

    The user selected a brand, e.g. Bank of America. The brand selection interface occurs before the institution select pane and is only provided for large financial institutions with multiple online banking portals.

    selectDegradedInstitution

    The user selected an institution with a DEGRADED health status and was shown a corresponding message.

    selectDownInstitution

    The user selected an institution with a DOWN health status and was shown a corresponding message.

    selectFilteredInstitution

    The user selected an institution Plaid does not support all requested products for and was shown a corresponding message.

    selectInstitution

    The user selected an institution.

    skipSubmitPhone

    The user has opted to not provide their phone number to Plaid. This event is only emitted in the Link Remember Me flow.

    submitAccountNumber

    The user has submitted an account number. This event emits the accountNumberMask metadata to indicate the mask of the account number the user provided.

    submitCredentials

    The user has submitted credentials.

    submitDocuments

    The user is being prompted to submit documents for an Income verification flow.

    submitDocumentsError

    The user encountered an error when submitting documents for an Income verification flow.

    submitDocumentsSuccess

    The user has successfully submitted documents for an Income verification flow.

    submitMFA

    The user has submitted MFA.

    submitOTP

    The user has submitted an OTP code during the phone number verification flow. This event is only emitted in the Link Returning User Experience (Remember Me) flow or the Layer flow. This event will not be emitted if the phone number is verified via SNA.

    submitPhone

    The user has submitted their phone number. This event is only emitted in the Link Remember Me flow.

    submitRoutingNumber

    The user has submitted a routing number. This event emits the routingNumber metadata to indicate user's routing number.

    transitionView

    The transitionView event indicates that the user has moved from one view to the next.

    uploadDocuments

    The user is asked to upload documents (for Income verification).

    verifyPhone

    The user has successfully verified their phone number via either OTP or SNA. This event is only emitted in the Link Returning User Experience (Remember Me) flow or the Layer flow.

    viewDataTypes

    The user has viewed data types on the data transparency consent pane.

    unknown

    The event has not been defined in the current version of the SDK. The unknown case has an associated value carrying the original event name as sent by the Plaid API.

    metadata
    EventMetadata structEventMetadata struct

    An object containing information about the event

    accountNumberMask
    Optional<String>Optional<String>

    The account number mask extracted from the user-provided account number. If the user-inputted account number is four digits long, account_number_mask is empty. Emitted by SUBMIT_ACCOUNT_NUMBER.

    errorCode
    Optional<ExitErrorCode>Optional<ExitErrorCode>

    The error code that the user encountered. Emitted by: error, exit.

    errorMessage
    Optional<String>Optional<String>

    The error message that the user encountered. Emitted by: error, exit.

    exitStatus
    Optional<ExitStatus>Optional<ExitStatus>

    The status key indicates the point at which the user exited the Link flow. Emitted by: exit.

    requiresQuestions

    User prompted to answer security question(s).

    requiresSelections

    User prompted to answer multiple choice question(s).

    requiresCode

    User prompted to provide a one-time passcode.

    chooseDevice

    User prompted to select a device on which to receive a one-time passcode.

    requiresCredentials

    User prompted to provide credentials for the selected financial institution or has not yet selected a financial institution.

    institutionNotFound

    User exited the Link flow on the institution selection pane. Typically this occurs after the user unsuccessfully (no results returned) searched for a financial institution. Note that this status does not necessarily indicate that the user was unable to find their institution, as it is used for all user exits that occur from the institution selection pane, regardless of other user behavior.

    unknown

    The exit status has not been defined in the current version of the SDK. The unknown case has an associated value carrying the original exit status as sent by the Plaid API.

    institutionID
    Optional<InstitutionID> (Optional<String>)Optional<InstitutionID> (Optional<String>)

    The ID of the selected institution. Emitted by: all events.

    institutionName
    Optional<String>Optional<String>

    The name of the selected institution. Emitted by: all events.

    institutionSearchQuery
    Optional<String>Optional<String>

    The query used to search for institutions. Emitted by: searchInstitution.

    isUpdateMode
    Optional<String>Optional<String>

    Indicates if the current Link session is an update mode session. Emitted by: OPEN.

    matchReason
    nullablestringnullable, string

    The reason this institution was matched. This will be either returning_user or routing_number if emitted by: MATCHED_SELECT_INSTITUTION. Otherwise, this will be SAVED_INSTITUTION or AUTO_SELECT_SAVED_INSTITUTION if emitted by: SELECT_INSTITUTION.

    linkSessionID
    StringString

    The link_session_id is a unique identifier for a single session of Link. It's always available and will stay constant throughout the flow. Emitted by: all events.

    mfaType
    Optional<MFAType>Optional<MFAType>

    If set, the user has encountered one of the following MFA types: code, device, questions, selections. Emitted by: submitMFA and transitionView when viewName is mfa

    requestID
    Optional<String>Optional<String>

    The request ID for the last request made by Link. This can be shared with Plaid Support to expedite investigation. Emitted by: all events.

    routingNumber
    Optional<String>Optional<String>

    The routing number submitted by user at the micro-deposits routing number pane. Emitted by SUBMIT_ROUTING_NUMBER.

    selection
    Optional<String>Optional<String>

    The Auth Type Select flow type selected by the user. Possible values are flow_type_manual or flow_type_instant. Emitted by: SELECT_AUTH_TYPE.

    timestamp
    DateDate

    An ISO 8601 representation of when the event occurred. For example 2017-09-14T14:42:19.350Z. Emitted by: all events.

    viewName
    Optional<ViewName>Optional<ViewName>

    The name of the view that is being transitioned to. Emitted by: transitionView.

    acceptTOS

    The view showing Terms of Service in the identity verification flow.

    connected

    The user has connected their account.

    consent

    We ask the user to consent to the privacy policy.

    credential

    Asking the user for their account credentials.

    documentaryVerification

    The view requesting Documentary Verification in the identity verification flow (configured via "Fallback Settings" in the "Rulesets" section of the template editor).

    error

    An error has occurred.

    exit

    Confirming if the user wishes to close Link.

    instantMicrodepositAuthorized

    The user has authorized an instant micro-deposit to be sent to their account over the RTP or FedNow network with a 3-letter code to verify their account.

    kycCheck

    The view representing the "know your customer" step in the identity verification flow.

    loading

    Link is making a request to our servers.

    mfa

    The user is asked by the institution for additional MFA authentication.

    numbers

    The user is asked to insert their account and routing numbers.

    numbersSelectInstitution

    The user goes through the Same-Day Micro-deposits flow with Reroute to Credentials.

    oauth

    The user is informed they will authenticate with the financial institution via OAuth.

    profileDataReview

    The user is asked to review their profile data in the Layer flow.

    recaptcha

    The user was presented with a Google reCAPTCHA to verify they are human.

    riskCheck

    The risk check step in the identity verification flow (configured via "Risk Rules" in the "Rulesets" section of the template editor).

    sameDayMicrodepositAuthorized

    The user has authorized a same day micro-deposit to be sent to their account over the ACH network with a 3-letter code to verify their account.

    screening

    The watchlist screening step in the identity verification flow.

    selectAccount

    We ask the user to choose an account.

    selectAuthType

    The user is asked to choose whether to Link instantly or manually (i.e., with micro-deposits).

    selectBrand

    The user is asked to select a brand, e.g. Bank of America. The brand selection interface occurs before the institution select pane and is only provided for large financial institutions with multiple online banking portals.

    selectInstitution

    We ask the user to choose their institution.

    selectSavedAccount

    The user is asked to select their saved accounts and/or new accounts for linking in the Link Remember Me flow.

    selectSavedInstitution

    The user is asked to pick a saved institution or link a new one in the Link Remember Me flow.

    selfieCheck

    The view in the identity verification flow which uses the camera to confirm there is a real user that matches their ID documents.

    submitPhone

    The user is asked for their phone number in the Link Remember Me flow.

    uploadDocuments

    The user is asked to upload documents (for Income verification).

    verifyPhone

    The user is asked to verify their phone OTP in the Link Remember Me flow.

    verifySMS

    The SMS verification step in the identity verification flow.

    unknown

    The view has not been defined in the current version of the SDK. The unknown case has an associated value carrying the original view name as sent by the Plaid API.

    metadataJSON
    RawJSONMetadata (String)RawJSONMetadata (String)

    Unprocessed metadata, formatted as JSON, sent from Plaid API.

    Select group for content switcher
    Swift
    let configuration = LinkTokenConfiguration(
        token: linkToken,
        onSuccess: { success in
            // Send success.publicToken to your app server.
        },
        onExit: nil,
        onEvent: { event in
            // Use event.eventName and event.metadata for analytics.
        },
        onLoad: nil
    )
    Objective-C
    configuration.onEvent = ^(PLKLinkEvent *event) {
        // Optionally handle event.eventName and event.metadata.
    };

    Additional flows

    Layer

    Layer uses a LayerTokenConfiguration and a PlaidLayerSession. Wait for .layerReady before presenting Layer.

    Select group for content switcher
    SwiftUI
    @State private var layerSession: PlaidLayerSession?
    @State private var isPresentingLayer = false
    
    var body: some View {
        EmptyView()
            .sheet(isPresented: $isPresentingLayer) {
                layerSession?.sheet()
            }
            .onAppear {
                createLayerSession()
            }
    }
    
    private func createLayerSession() {
        let configuration = LayerTokenConfiguration(
            token: linkToken,
            onSuccess: { _ in isPresentingLayer = false },
            onExit: { _ in isPresentingLayer = false },
            onEvent: { event in
                if event.eventName == .layerReady {
                    isPresentingLayer = true
                }
            }
        )
    
        do {
            layerSession = try Plaid.createPlaidLayerSession(configuration: configuration)
        } catch {
            // Handle the error.
        }
    }
    UIKit
    final class LayerViewController: UIViewController {
        private let linkToken: String = "<#LINK_TOKEN_FROM_SERVER#>"
        private var layerSession: PlaidLayerSession?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            createLayerSession()
        }
    
        private func createLayerSession() {
            let configuration = LayerTokenConfiguration(
                token: linkToken,
                onSuccess: { _ in
                    // Handle success.
                },
                onExit: { _ in
                    // Handle exit.
                },
                onEvent: { [weak self] event in
                    if event.eventName == .layerReady {
                        guard let self = self else { return }
                        self.layerSession?.open(using: .viewController(self))
                    }
                }
            )
    
            do {
                layerSession = try Plaid.createPlaidLayerSession(configuration: configuration)
            } catch {
                // Handle the error.
            }
        }
    }
    =*=*=*=

    submit()

    The submit(data:) function is currently only used in the Layer product. It allows the client application to submit additional user-collected data to the Link flow, such as a phone number or date of birth.

    submit

    Properties

    submissionData
    objectobject

    Data to submit during a Link session.

    phoneNumber
    StringString

    The end user's phone number.

    dateOfBirth
    StringString

    The end user's date of birth. To be provided in the format "yyyy-mm-dd".

    To submit user data to Layer, create a model that conforms to SubmissionData.

    struct PlaidSubmitData: SubmissionData {
        var phoneNumber: String?
        var dateOfBirth: String?
    }
    
    let data = PlaidSubmitData(phoneNumber: "14155550015", dateOfBirth: "1975-01-18")
    layerSession?.submit(data: data)
    Headless Link

    Headless Link uses a PlaidHeadlessSession. Create the session, retain it, and call start() when the session is ready.

    Select group for content switcher
    SwiftUI
    @State private var headlessSession: PlaidHeadlessSession?
    
    let configuration = LinkTokenConfiguration(
        token: linkToken,
        onSuccess: { success in
            // Handle success.
        },
        onExit: { exit in
            // Handle exit.
        },
        onEvent: { event in
            // Handle events.
        },
        onLoad: {
            headlessSession?.start()
        }
    )
    
    do {
        headlessSession = try Plaid.createHeadlessSession(configuration: configuration)
    } catch {
        // Handle the error.
    }
    UIKit
    private var headlessSession: PlaidHeadlessSession?
    
    let configuration = LinkTokenConfiguration(
        token: linkToken,
        onSuccess: { success in
            // Handle success.
        },
        onExit: { exit in
            // Handle exit.
        },
        onEvent: { event in
            // Handle events.
        },
        onLoad: { [weak self] in
            self?.headlessSession?.start()
        }
    )
    
    do {
        headlessSession = try Plaid.createHeadlessSession(configuration: configuration)
    } catch {
        // Handle the error.
    }
    Embedded Institution Search

    Embedded Institution Search uses EmbeddedLinkTokenConfiguration. Create the embedded view before displaying it to reduce latency.

    Select group for content switcher
    SwiftUI
    struct EmbeddedInstitutionSearchView: View {
        let linkToken: String
        @State private var embeddedSearchView: EmbeddedSearchView?
    
        var body: some View {
            VStack {
                if let embeddedSearchView {
                    embeddedSearchView
                }
            }
            .onAppear(perform: createEmbeddedSearchView)
        }
    
        private func createEmbeddedSearchView() {
            let configuration = EmbeddedLinkTokenConfiguration(
                token: linkToken,
                onSuccess: { success in
                    // Handle success.
                },
                onExit: { exit in
                    // Handle exit.
                },
                onEvent: { event in
                    // Handle events.
                }
            )
    
            do {
                embeddedSearchView = try Plaid.createEmbeddedLinkView(configuration: configuration)
            } catch {
                // Handle the error.
            }
        }
    }
    UIKit
    final class EmbeddedInstitutionSearchViewController: UIViewController {
        private let linkToken: String = "<#LINK_TOKEN_FROM_SERVER#>"
    
        override func viewDidLoad() {
            super.viewDidLoad()
            createEmbeddedSearchView()
        }
    
        private func createEmbeddedSearchView() {
            let configuration = EmbeddedLinkTokenConfiguration(
                token: linkToken,
                onSuccess: { success in
                    // Handle success.
                },
                onExit: { exit in
                    // Handle exit.
                },
                onEvent: { event in
                    // Handle events.
                }
            )
    
            do {
                let embeddedView: EmbeddedSearchUIView = try Plaid.createEmbeddedLinkUIView(
                    configuration: configuration,
                    presentationMethod: .viewController(self)
                )
    
                embeddedView.translatesAutoresizingMaskIntoConstraints = false
                view.addSubview(embeddedView)
    
                NSLayoutConstraint.activate([
                    embeddedView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
                    embeddedView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
                    embeddedView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
                    embeddedView.heightAnchor.constraint(equalToConstant: embeddedView.expectedHeight),
                ])
            } catch {
                // Handle the error.
            }
        }
    }

    Next steps

    Once you've gotten Link working, see Link best practices for recommendations on improving the Link flow.

    Developer community
    GitHub
    GitHub
    Stack Overflow
    Stack Overflow
    YouTube
    YouTube
    Discord
    Discord