First, we will define a wrapper struct that will encapsulate all the data required to construct an API request object for the Last10k.com developers website. This struct will define a nested enum type whose cases will represent the differnet REST API endpoints and whose rawValue type will be a string.

struct EdgarAPIRequest{
    
    enum APIEndpoint: String{
        case BalanceSheet = "balancesheet"
        case IncomeStatement = "income"
        case CashFlows = "cashflows"
        case FinancialRatios = "ratios"
    }
}
    

In the EdgarAPIRequest class, we will also define some string constants that will be needed to construct the url for the API request, as well as to configure the header fields for the API request. The baseURL will be used to construct the API request url. The headerFieldKey is a key that is defined for API request header fields, with corresponding values provided by the constants primaryKey and secondaryKey. Please note that the keys provided here are for demonstration purposes only and will not work in an actual production environment. To practice the code below for yourself, you can register for an account with Last10k.com and get your own free API keys.


    let baseURL = "https://services.last10k.com/v1/company"
    let primaryKey = "1afa19akdf800f43b096fc9cbd36adfd99888"
    let secondaryKey = "bafd99gfdadf58b300f4a8fdll0w2aea9541cfakfdiie99"
    let headerFieldKey = "Ocp-Apim-Subscription-Key"
    
    

In addition to the constants defined above, we will also define other properties that will be used to build the API request url. The formType and filingOrder variables are optional strings which correspond to optional query parameters in the url string. the ticker string variable is provided during initialization of the EdgarAPIRequest, as is the value of the endpoint variable, whose data type is the APIEndpoint we defined above and whose string rawValue can be used to construct the url for the API request.

    var ticker: String
    var endpoint: APIEndpoint
    var formType: String?
    var filingOrder: String?
    

With all the variables defined, as shown above, we proceed to define an initializer for the EdgarAPIRequest struct:

        
    init(withTicker companyTicker: String, andWithEndpoint apiEndpoint: APIEndpoint, withFormType formType: String?, withFilingOrder filingOrder: String?){
        
        self.ticker = companyTicker
        self.endpoint = apiEndpoint
        self.formType = formType
        self.filingOrder = filingOrder
        
    }
    

Finally, with all of our data members initialized, we go on to define a private helper method getURL for constructing the URL for the API request, and a publicly available method for generating the actual API request object. This public method will also use the API key to set the value for the required authentication header field in the API request:




    func getURLRequest() -> URLRequest{
        
        let urlString = getURL()
        let url = URL(string: urlString)!
        
        var urlRequest = URLRequest(url: url)
        
        urlRequest.setValue(self.primaryKey, forHTTPHeaderField: self.headerFieldKey)
        
        return urlRequest
    }
    
    private func getURL() -> String{
        
        var url = "\(self.baseURL)/\(self.ticker)/\(self.endpoint.rawValue)"
        
        switch (self.formType,self.filingOrder) {
        case (.some,.some):
            url = url.appending("/?\(formType!)&\(filingOrder!)")
            break
        case (.some,.none):
            url = url.appending("/?\(formType!)")
            break
        case (.none,.some):
            url = url.appending("/?\(filingOrder!)")
            break
        default:
            break
        }
        
        return url
        
        
    }

    
		
	

Now that we have defined our EdgarAPIRequest struct, we can proceed to define a reference-type class APIRequestNode node, whose variable nextNode will be a self-referencing variable that can be used to link to the next node in a linked list. In addition, we define a variable apiRequest, which will provide the actual data content for the node. We define two initializers for the node: one that will take an EdgarAPIRequest as a parameter, and another that takes the parameters required to initialize an EdgarAPIRequest within the body of the initializer itself.

class APIRequestNode{
    
    var apiRequest: EdgarAPIRequest
    
    var nextNode: APIRequestNode?
    
    init(withAPIRequest anAPIRequest: EdgarAPIRequest){
        self.apiRequest = anAPIRequest
    }
    
    init(withTicker ticker: String, withEnpoint endpoint: EdgarAPIRequest.APIEndpoint, withFormType formType: String?,withFilingOrder filingOrder: String?){
        
        self.apiRequest = EdgarAPIRequest(withTicker: ticker, andWithEndpoint: endpoint, withFormType: formType, withFilingOrder: filingOrder)
        
    }
    
  
}

    

Finally, we define a getter method getAPIRequest for retrieving the API request from a node, and a separate getter method getNextAPIRequestNode, which can be used to retrieve the next node in a linked list. In addition, we provide two setter methods, setNextAPIRequest(withTicker:withEndpoint:withFormType:withFilingOrder) and setNextAPIRequest(withAPIRequest:), which can be used to set the next node in the linked list. Note that these setter functions also have a return value, allowing us to more conveniently chain a series of setter functions together so as to generate a linked list.

    func getAPIRequest() -> EdgarAPIRequest{
        return self.apiRequest
    }
    
    func setNextAPIRequest(withTicker ticker: String, withEndpoint endpoint: EdgarAPIRequest.APIEndpoint,withFormType formType: String?, withFilingOrder filingOrder: String?) -> APIRequestNode{
        
        self.nextNode = APIRequestNode(withTicker: ticker, withEnpoint: endpoint, withFormType: formType, withFilingOrder: filingOrder)
        
        return self.nextNode!
    }
    
    func setNextAPIRequest(withAPIRequest anAPIRequest: EdgarAPIRequest) -> APIRequestNode{
        self.nextNode = APIRequestNode(withAPIRequest: anAPIRequest)
        
        return self.nextNode!
    }
    
    func getNextAPIRequestNode() -> APIRequestNode?{
        return self.nextNode
    }
    

As of now, the structs and classes provide enough functionality to build our API class. However, we will also continue to define a class that can be used to generate a linked list using APIRequestNode objects that we've just defined. For our purposes here, the linked list class will be used primarily for debugging the content of the linked lists that we create for generating a series of API requests. The linked list class APIRequestNodeList is show below in its entirety:

        
class APIRequestNodeList{
    
    var rootNode: APIRequestNode
    
    
    func getFirstNode() -> APIRequestNode{
        return self.rootNode
    }


    init?(withAPIRequests someAPIRequests: [EdgarAPIRequest]){
        
        if(someAPIRequests.isEmpty || someAPIRequests.count == 0){
            return nil
        } else if (someAPIRequests.count == 1){
            self.rootNode = APIRequestNode(withAPIRequest: someAPIRequests.first!)
        } else {
            
            self.rootNode = APIRequestNode(withAPIRequest: someAPIRequests.first!)

            var tempNode = self.rootNode
            
            let remainingRequests = someAPIRequests[1..<someAPIRequests.count]
            
            remainingRequests.forEach({
                
                tempNode = tempNode.setNextAPIRequest(withAPIRequest: $0)
                
            })
            
        }
        
        
        
    }


func traverseAPIRequests(withHandler handler: (EdgarAPIRequest) -> (Void)){
        
        let firstAPIRequest = self.rootNode.getAPIRequest()
        handler(firstAPIRequest)
        
        var currentNode = self.rootNode.getNextAPIRequestNode()
        
        repeat{
            
            if(currentNode != nil){
                handler(currentNode!.getAPIRequest())
            }
            
            currentNode = currentNode?.getNextAPIRequestNode()
            
        } while(currentNode != nil)
        
    }
    

    
   
}


    

We are now ready to go ahead and build the class that will be responsible for making the API requests for the Last10k.com REST API endpoint. We've created our wrapper struct EdgarAPIRequest, which will encapsulate the data for making the API request object, along with classes for creating node objects to encapsulate EdgarAPIRequest data and also link together so as to create a linked list whose nodes can be traversed in such a way as to make it possible for us to make a series of API requests to the Last10k.com REST API endpoint.

To continue, please click here

If you feel confused or are having trouble following, you can go back to the previous page or back to the table of contents table of contents.