iOS

Learn how to get started with Citadel API for your iOS application

Setup for iOS

Once you have your API keys, it's time to run the Citadel iOS Quickstart app locally.
Requirements: XCode and Simulator

  1. git clone https://github.com/citadelid/quickstart-ios
  2. cd quickstart-ios
  3. Create a citadel-quickstart/Constants.swift file with the following content (values with <> should be replaced by the proper keys or values):
import Foundation

var CitadelClientID = "<client_id>"
var CitadelClientSecret = "<access_key>"
var CitadelAPIUrl = "https://prod.citadelid.com/v1/"
var CitadelProductType = "<employment or income>"
  1. Open the project in XCode and run the app

Run Quickstart

The iOS Quickstart app emulates the experience of an applicant going through an employment and income verification.

After opening the Quickstart app you will be presented with the Citadel Bridge.

Use the Sandbox credentials to successfully connect a payroll account.

When you click "Done" at the end of Bridge you will be able to see the data returned by the Citadel API.

Step-by-step overview

This flow involves a user, the application front end, the application back end and the Citadel API. You can see a visual diagram of tokens and data exchange in Bridge section of docs.

1. Authorize and initialize Bridge

Your app sends an API request to Citadel for bridge_tokenbridge_token - A short-lived token provided by the Citadel API to authorize the use of Bridge. This token has a 6 hour expiration..

citadel.getBridgeToken() { bridgeToken, error in
func getBridgeToken (completionHandler:@escaping (String?, Error?) -> Void ) -> URLSessionTask {
    let url = URL(string: "\(CitadelAPIUrl)bridge-tokens/")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue(CitadelClientID, forHTTPHeaderField: "X-Access-Client-Id")
    request.setValue(CitadelClientSecret, forHTTPHeaderField: "X-Access-Secret")
        
    let task = URLSession.shared.dataTask(with: request) { data, response, error -> Void in
      guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        completionHandler(nil, error)
        return
      }
    
      do {
        let decoder = JSONDecoder()
        let decodedData = try decoder.decode(BridgeTokenResponse.self, from: data)
        completionHandler(decodedData.bridge_token, nil)
        return
      } catch {
        print("Something went wrong")
        completionHandler(nil, error)
        return
      }
    }
    task.resume()
    return task
  }

Your app loads a mobile page from Citadel's CDN with bridge_tokenbridge_token - A short-lived token provided by the Citadel API to authorize the use of Bridge. This token has a 6 hour expiration. into native WebView.

let uuid = NSUUID().uuidString
  var components = URLComponents(string: "https://cdn.citadelid.com/mobile.html")
  components?.queryItems = [URLQueryItem(name: "bridge_token", value: bridgeToken)]
  let myRequest = URLRequest(url: (components?.url)!)
  self.webView.load(myRequest)

2. User connects account

The user selects an employer, choses their provider, logs in, and clicks Done. public_tokenpublic_token - A short-lived token used to exchange for an *access_token* from the backend. This token has a 6 hour expiration. is generated.

let publicToken = (payload?["public_token"] as! String)
  citadel.getAccessToken(publicToken: publicToken) { accessToken, error in
    if(CitadelProductType == "employment") {
      self.setupEmployment(accessToken: accessToken!)
    } else {
      self.setupIncome(accessToken: accessToken!)
    }
  }

Your backend sends an API request to Citadel exchanging the temporary token for the access_tokenaccess_token - A private token unique to a single Link. Used to access Link data and initiate any actions using the same Link.

func getAccessToken (publicToken: String, completionHandler:@escaping (String?, Error?) -> Void ) -> URLSessionTask {
    let url = URL(string: "\(CitadelAPIUrl)access-tokens/")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue(CitadelClientID, forHTTPHeaderField: "X-Access-Client-Id")
    request.setValue(CitadelClientSecret, forHTTPHeaderField: "X-Access-Secret")
    let json: [String: Any] = ["public_tokens": [publicToken]]
    do {
      let jsonData = try JSONSerialization.data(withJSONObject: json)
      request.httpBody = jsonData
    } catch {
      print("Access Token Error")
      print(error)
      completionHandler(nil, error)
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error -> Void in
      guard let data = data, error == nil else {
          print(error?.localizedDescription ?? "No data")
          completionHandler(nil, error)
          return
      }
      do {
        let decoder = JSONDecoder()
        let decodedData = try decoder.decode(AccessTokenResponse.self, from: data)
        completionHandler(decodedData.access_tokens.first, nil)
      } catch {
        print("Something went wrong")
        print(error)
        completionHandler(nil, error)
      }
    }
    task.resume()
    return task
  }

3. Get data from API

Your backend sends an API request to Citadel with the access_tokenaccess_token - A private token unique to a single Link. Used to access Link data and initiate any actions using the same Link for employment/income verification.

func getEmploymentInfoByToken (accessToken: String, completionHandler:@escaping ([String: Any]?, Error?) -> Void ) -> URLSessionTask {
    let url = URL(string: "\(CitadelAPIUrl)verifications/employments/")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue(CitadelClientID, forHTTPHeaderField: "X-Access-Client-Id")
    request.setValue(CitadelClientSecret, forHTTPHeaderField: "X-Access-Secret")
    let json: [String: Any] = ["access_token": accessToken]
    do {
      let jsonData = try JSONSerialization.data(withJSONObject: json)
      request.httpBody = jsonData
    } catch {
      print("Employment Info by Token Error")
      print(error)
      completionHandler(nil, error)
    }
        
    let task = URLSession.shared.dataTask(with: request) { data, response, error -> Void in
      guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        completionHandler(nil, error)
        return
      }
      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
      completionHandler(json, nil)
    }
    task.resume()
    return task
    }

Your app renders the data sent back by Citadel API for the user.

let finalView = EmploymentView(data: result!)
                    
  self.webView.removeFromSuperview()
  self.view.addSubview(finalView)

Did this page help you?