Supported response formats: JSON over HTTPS
All requests and responses to the Prosper Investor APIs support the JSON format over HTTPS.

Supported API methods
Most Prosper API calls you make will be GET calls, used to retrieve resources. When larger data sets are expected, GET calls support pagination, which is described below.

Some APIs additionally support the POST method, when you want to pass information to a Prosper API.

Making secure API calls
Prosper APIs use OAuth 2.0 to authorize client access to a Prosper user’s resources.

Once you have received an OAuth access token, making calls into Prosper APIs is a fairly simple process. The process is shown in the following diagram.

Client Making An API Call

Your client makes a Prosper API call, passing in an access token. If the access token is valid and has not expired, and the resource is owned by the user bearing the access token, Prosper responds with the requested resource. In some cases, such as when a POST call is being made, you may pass in a JSON request body with the request. However, in most cases, you will be requesting resources to inspect using a GET call.

If the access token has expired, you will receive an error, and will need to get another access token. It’s good practice for your client to make note of the time when you first receive an access token, and to retrieve a new one with your refresh token right before it expires. You can refresh access tokens many times throughout the day, as refresh tokens expire after 10 hours. For more information, see Authenticating with OAuth 2.0.

Example API call
Here’s a GET call to retrieve listings.

GET /listingsvc/v2/listings/
   Authorization: bearer <access_token>
   Accept: application/json
   timezone: America/Los_Angeles

Each API call must include Authorization and Accept HTTP headers. Optionally, you may pass in the timezone for which you want all times returned in the response.

The Authorization HTTP header includes the token type (bearer) along with the access token you received when you requested an OAuth token. The token gives your client permission to retrieve the resources owned by your account.

The Accept HTTP header tells Prosper to return the response in JSON format.

The optional timezone HTTP header tells Prosper to return all dates in the response in the timezone you request. The above example defines the timezone as America/Los_Angeles.

Note: All Prosper APIs return dates in UTC format. If you want to retrieve dates and times that match your timezone, pass a timezone parameter as part of the header when making the call.


Paginating your responses
When making calls to retrieve multiple objects, it is best to make multiple requests and paginate the results. To do this, use the limit and offset parameters when making a GET call to retrieve multiple objects.

Name Description
offset Defaults to 0.

The starting object within the query result set when paginating. When making calls that may return a large result set, it is beneficial to page the result set. By paginating your result set, you will get a much faster response than when requesting a larger, potentially large, data set for the limit value.

Example: If your first call specifies an offset of 0, and a limit of 25, your second call would have an offset value of 25. Your third call would have an offset value of 50. Your fourth call would have an offset value of 75, and so forth.

limit Differs for each API. See the limit value on the page that describes the API you’re using.

Determines how many objects to return in the result set. There may be less remaining objects than the value you specify for the limit.


Request Throttling
We restrict our API volume to 20 requests per second across all investors, per Client ID + username combination.


Error handling
Errors will be passed back to you in the following standard format:

{
   "code": string,  -- error code
   "message": string, -- error message
   "errors": [   {     -- list of errors for the call
      "code": String   - error code,
      "message": String  -- error message
   }]
}

The following error shows what might appear when a bad parameter is passed into a method call:

{
   "code": "AP1008",
   "message": "Validation failed on input parameters",
   "errors": [   {
      "code": "APP1007",
      "message": "The following fields have invalid or unsupported value asdfdasflkj"
   }]
}

Best practices for avoiding rate limiting and making Oauth call

var CurrentRequestCount = 0
var MaxAmountOfRequests = 20
var RateLimitWindowInMilliseconds = 1000
var FirstRequestTimestampInMilliseconds = NowAsMilliseconds()

var refreshToken
var accessToken

function waitIfRateLimited() {
    if ((NowAsMilliseconds() - FirstRequestTimestampInMilliseconds) > RateLimitWindowInMilliseconds) {
        CurrentRequestCount = 0
        FirstRequestTimestampInMilliseconds = NowAsMilliseconds()
    }

    if (CurrentRequestCount >= MaxAmountOfRequests) {
        waitForOneSecond()
    } else {
        CurrentRequestCount++
    }
}

function getNewAccessTokenWithRefreshToken() {
    // Get new access token with refresh token
    Response response = httpClient.post("https://api.prosper.com/v1/security/oauth/token", {
        "Accept": "application/json",
        "Content-Type": "application/x-www-form-urlencoded",
        "body": {
            "grant_type": "refresh_token",
            "client_id": "{your_client_id}",
            "client_secret": "{your_client_secret}",
            "refresh_token": "{refreshToken}"
        }
    });

    if (response.Code == 200) {
        accessToken = response.Body["access_token"];
        refreshToken = response.Body["refresh_token"];
    } else if (response.Code == 401) {
		getInitialAccessToken();
	} else {
        // Handle failed refresh token request such as retry few times
    }
}

function getInitialAccessToken() {
    // Get initial access token
    Response response = httpClient.post("https://api.prosper.com/v1/security/oauth/token", {
        "Accept": "application/json",
        "Content-Type": "application/x-www-form-urlencoded",
        "body": {
            "grant_type": "{your_grant_type}",  // Replace with your grant type
            "client_id": "{your_client_id}",
            "client_secret": "{your_client_secret}",
            // Add other necessary fields depending on your grant type
        }
    });

    if (response.Code == 200) {
        accessToken = response.Body["access_token"];
        refreshToken = response.Body["refresh_token"];
    } else {
        // Handle failed initial access token request such as retry for few times
    }
}

function makeApiCall() {
    waitIfRateLimited()

    // Make API call with current access token
    Response response = httpClient.get("{your_api_endpoint}", {
        "Authorization": "Bearer " + accessToken
    });

    // If 401 response, try refreshing access token and make API call again
    if (response.Code == 401) {
        getNewAccessTokenWithRefreshToken()

        // Make API call again with new access token
        response = httpClient.get("{your_api_endpoint}", {
            "Authorization": "Bearer " + accessToken
        });
    }

    // Handle response (either success or another error)

    return response
}

function main() {
    getInitialAccessToken()  // Get the initial access token

    while (true) {
        makeApiCall()
        // Add any required delay or conditions to break the loop
    }
}