The basics of working with Pngme's APIs

Welcome!

This guide provides a high-level walk-thru of key steps in working with Pngme's APIs.

By the end of this guide, you should understand:

  1. How to fetch an API token to authenticate API cals
  2. How to call Pngme's risk-scoring endpoint /decision API to retrieve a loan-overdue prediction
  3. (optional) How to enforce data-freshness for near-realtime decisioning of first-time mobile app users

Requirements

  • The Pngme SDK is live in your organizations mobile app
  • You have a Pngme account and can sign in at admin.pngme.com. If you cannot sign in, or your login is not associated with your organization's mobile app, then please contact your organization's account administrator and/or contact Pngme support for assistance.

Let's go!

API tokens

You'll need a JSON web token to authenticate your API requests. API tokens are valid for 12 hours.

API tokens are sensitive credentials since they can be used to access users' financial data. Treat them the same as other sensitive data, such as your password.

You can access an API token in one of two ways:

  1. Log in to admin.pngme.com and copy the token from the Keys page.
  2. Programmatically fetch a token from the /auth API. Pass the same email and password you use at admin.pngme.com in the Authorization header. Authorization: Basic {base64(email:password)}

👍

Best Practice

Pngme suggests that organizations add a service account for production environments, for example [email protected]. Email addresses can be added to your organization's account in the admin dashboard. A service account email must be a valid (real) email address, capable of receiving verification emails.

Example

The below pseudo code illustrates the procedure for calling the /decision API to get the risk score (loan overdue probability) for a mobile phone user in Nigeria.

📘

Time-aware predictions

By default, a call to the the /decisionAPI will calculate a prediction based on all mobile phone transactions that occurred at a time up-to now(). If you are doing retroactive analysis, you may want to generate predictions based only on financial transactions up-to a prior timestamp. This is possible with an optional query parameter. See the API Reference for details.

LOGIN_EMAIL = "[email protected]"
LOGIN_PASSWORD = "[email protected]!"
ORGANIZATION_NAME = "acme"  # your organization name listed in the admin dashboard
ENVIRONMENT = "production"  # if your mobile app is live, this will be production

# step 1 - fetch api token
# -----------------------
def fetch_token_api(email, password):
    url = "https://api.pngme.com/beta/auth"
  # call GET to API here...
  response = [{
    "organization_name": "acme",
    "organization_uuid": "000-000...",
    "auth": [{"type": "production", "api_token": "eyJh...", "sdk_token": "..."}]
  }]
  api_token = None
  for org in response:
      if org["organization_name"] == ORGANIZATION_NAME:
        for environment in org["auth"]:
          if environment["type"] == ENVIRONMENT:
            api_token = environment["api_token"]
    return api_token


# step 2 - fetch loan overdue prediction
# -------------------------
def fetch_decision_api(app_user_phone, api_token):
  url = "https://api.pngme.com/beta/nigeria/decision"
  # call GET to API here...
  response = {
  "user": {...},
  "data_recency_minutes": 83,
  "risk_score": 0.53,
  "features": {
    "average_end_of_day_depository_balance_0_30": 6233.53,
    "average_end_of_day_depository_balance_0_90": 6104.64,
    ...
    }
  }
  return response["risk_score"]

  
# RUN - put it all together...
app_user_phone_number = "2343456789011"  # this is the phone number registered via the android SDK in the mobile app

# note: tokens last for 12 hours 
token = fetch_token_api(LOGIN_EMAIL, LOGIN_PASSWORD)

risk_score = fetch_decision_api(app_user_phone_number, token)
print(risk_score)


Data freshness

Pngme builds its datasets from mobile phone SMS. For first-time mobile app users, it can sometimes take as long at 5 minutes for Pngme to capture all the SMS on the user's phone and generate a complete dataset (this time estimate is impacted by mobile carrier network speeds and the volume of SMS on the user's phone).

If your system expects to call the Risk Score /decision endpoint within 5 minutes, you may want to consider implementing smart backoff logic when calling the /decision endpoint. Calling the /decision endpoint too early for first-time users may result in the endpoint returning an empty null value for the prediction, when waiting a bit longer may otherwise have produced a confident non-null prediction.

Pngme provides a data_recency_minutes value available from the /decision API which can be used to intelligently wait until Pngme captures a suitably large dataset before which would result in a valid risk score.

A backoff and retry can be added to the above pseudo-code with the additional logic:

MAX_WAIT_TIME_SEC = 120  # maximum time, in seconds, system is wiling to wait when fetching /decision
BACKOFF_BETWEEN_CALLS_SEC = 15  # wait time between calls to check for data freshness
MAX_DATA_RECENCY_MINUTES = 10000. # Pngme's recommended freshness threshold

# (optional) step 3 - fetch data freshness metric
# -------------------------
def fetch_data_recency_minutes(app_user_phone, api_token):
    url = "https://api.pngme.com/beta/{country}/decision"
    # call GET API here
  response = {
  "user": {...},
  "data_recency_minutes": 18100,
  "risk_score": ...,
  "features": {
    "count_loan_defaulted_events_0_90": null,
    ...
    }
  }
  return response["data_recency_minutes"]


# RUN - put it all together...
app_user_phone_number = "2343456789011"  # this is the phone number registered via the android SDK in the mobile app

# note: tokens last for 12 hours 
token = fetch_token_api(LOGIN_EMAIL, LOGIN_PASSWORD)

risk_score = None

max_attempts = MAX_WAIT_TIME_SEC / BACKOFF_BETWEEN_CALLS_SEC
attempts = 0
while attempts < max_attempts:
    data_recency_minutes = fetch_data_recency_minutes(app_user_phone_number, api_token)
  if data_recency_minutes <= MAX_DATA_RECENCY_MINUTES:
    risk_score = fetch_decision_api(app_user_phone_number, token)
        break
    max_attempts = max_attempts + 1

print(risk_score)