Paging Data

To retrieve all opportunities you must utilize the continuation-token header and page through the data by making multiple sequential requests to the API.

Limit Query Parameter Required

In order to use this feature you must always set the limit parameter in your query string. See the Opportunity Querying section for details on this property.

The maximum size of the response is ~50MB, so if the limit is set to something large the number of opportunities returned can vary from request to request based on the size of the JSON data containing all the opportunities in that response.

First Request

The first request you make to the GET \opportunities endpoint does not require the continuation-token header. When you get back the first response it will include three important headers:

  • count - Number of opportunities retrieved in this request
  • total-count - Total number of opportunities that can be retrieved. This is including the ones just retrieved. For example: if you have 200 opportunities and retrieve all of them both count and total-count will be 200.
  • continuation-token - Token that should be placed into a sequential request’s continuation-token header to retrieve the next page of data.

Sequential Requests

If count is less than total-count you can then make another request using the continuation-token header and settings its value to the token retrieved from your response’s continuation-token header. This will retrieve the next page of data. This process can be repeated until count = total-count. Continuing this process after that point will restart from the first page again.

C# Example

Below is an example C# implementation of paging through the data via the GET \opportunities endpoint.

OpportunityPage Class
Holds the relevant response data from the API.
public class OpportunityPage
    public string ContinuationToken { get; }
    public string ResponseJSON { get; }

    public int TotalCount { get; }
    public int BatchCount { get; }

    public bool MoreToGet => TotalCount > 0 && 
                             BatchCount > 0 &&
                             BatchCount < TotalCount;

    public OpportunityPage(string sContinuationToken, string sResponse, int iTotalCount, int iBatchCount)
        ContinuationToken = sContinuationToken;
        ResponseJSON = sResponse;
        TotalCount = iTotalCount;
        BatchCount = iBatchCount;
IAPI Interface
Interface for implementating a GET API.
public interface IAPI
    Task<OpportunityPage> GetPage(string sContinuationToken = "");
Base API Abstract Class
Includes the EncodeToBase64(string sStringToEncode) method used in the child Opportunities class.
public abstract class BaseAPI : IAPI
    public abstract Task<OpportunityPage> GetPage(string sContinuationToken = "");

    protected static string EncodeToBase64(string sStringToEncode)
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(sStringToEncode));
Opportunities Class
Includes the implementation of GetPage(string sContinuationToken = "") which retrieves a page of data from the PrecisionLender V2 API.
public class Opportunities : BaseAPI
    private const string HEADER_CLIENT_ID = "clientId";
    private const string HEADER_AUTH = "Authorization";
    private const string HEADER_CONTINUATION_TOKEN = "Continuation-Token";
    private const string HEADER_COUNT = "Count";
    private const string HEADER_TOTAL_COUNT = "Total-Count";
    private const string HEADER_LIMIT = "limit";

    private readonly string _url;

    public Opportunities(int iPageSize = 100)
        _url = string.Format("{0}?limit={1}", "", iPageSize);
    /// <summary>
    /// Retrieve a page of data from the PrecisionLender V2 API
    /// </summary>
    /// <param name="sContinuationToken"></param>
    /// <returns></returns>
    public override async Task<OpportunityPage> GetPage(string sContinuationToken = "")
        OpportunityPage opportunityPage = new OpportunityPage(string.Empty, string.Empty, 0, 0);

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
        request.Headers.Add(HEADER_CLIENT_ID, "YOUR_CLIENT_ID");
        request.Headers.Add(HEADER_AUTH, "Basic " + EncodeToBase64("YOUR_USER_NAME:YOUR_PASSWORD"));

        // If we have a continuation token then add it as a header to the request
        if (string.IsNullOrEmpty(sContinuationToken) == false)
            request.Headers.Add(HEADER_CONTINUATION_TOKEN, sContinuationToken);

        using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
            // Check to see if any opportunities were brought back from the API and if so load the response
            // data into the OpportunityPage class
            if (int.TryParse(response.Headers.Get(HEADER_COUNT), out int iBatchCount) && iBatchCount > 0)
                using (Stream stream = response.GetResponseStream())
                using (StreamReader reader = new StreamReader(stream))
                    string sResponseBody = await reader.ReadToEndAsync();
                    int iTotalCount = Convert.ToInt32(response.Headers.Get(HEADER_TOTAL_COUNT));
                    sContinuationToken = response.Headers.Get(HEADER_CONTINUATION_TOKEN);

                    opportunityPage = new OpportunityPage(sContinuationToken, sResponseBody, iTotalCount, iBatchCount);

        return opportunityPage;
Calling the API
This code demonstrates how to call the API through the IAPI implementation created above and page through the data. It simply writes out the total count of opportunities and how many were pulled in the batch, but OpportunityPage also includes the JSON data from the body for your usage.
IAPI api = new Opportunities(1000);
string sContinuationToken = string.Empty;
OpportunityPage oppPage;

    oppPage = await api.GetPage(sContinuationToken);
    sContinuationToken = oppPage.ContinuationToken;

    await Console.Out.WriteLineAsync(string.Format("Total opportunities: {0}\r\nOpportunities in batch: {1}\r\n", oppPage.TotalCount, oppPage.BatchCount));
while (oppPage.MoreToGet);

await Console.Out.WriteLineAsync("Complete!");