The basics of working with Pngme's APIs


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 back-off and retry to ensure enough elapsed time for near-realtime decisioning of first-time mobile app users


  • The Pngme SDK is live in your organizations mobile app
  • You have a Pngme account and can sign in at 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 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 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.


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 = "strOng_p@assword!"
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 = ""
  # 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 = ""
  # 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)

Near Real-time decisioning

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).

Pngme highly recommends engineering your product and decisioning system to provide guarantees that at least 5minutes elapses between when the Pngme SDK is invoked on a user's phone, and when you call Pngme endpoints to retrieve data. This avoids the "data race condition", simplifying integration all-around.

If your system expects to call the Risk Score /decision endpoint within 5 minutes, however, you may want to consider implementing smart backoff and retry logic when calling the /decision endpoint to ensure that at least 5 minutes elapses on all API calls.

This backoff and retry can be implemented using the "user_created_at_elapsed_minutes" key returned from the the /decision API. This key-value provides the time, in minutes, since the user was created in our system. The back-off and retry logic simply says "if the user was created in Pngme's system fewer than 5minutes ago, then wait a bit, and try calling back again".

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

MAX_WAIT_TIME_SEC = 5 * 60  # maximum time, in seconds, system is willing to wait when fetching /decision
BACKOFF_BETWEEN_CALLS_SEC = 30  # wait time between calls
TIME_ELAPSED_THRESHOLD_MINUTES =  5  # Pngme's recommended wait period after a new user is created

# (optional) step 3 - fetch elapsed time between when user was created and now
# -------------------------
def fetch_user_created_at_elapsed_minutes(app_user_phone, api_token):
	url = "{country}/decision"
	# call GET API here
  response = {
  "user": {...},
  "user_created_at_elapsed_minutes": 3,
  "risk_score": ...,
  "features": {
    "count_loan_defaulted_events_0_90": null,
  return response["user_created_at_elapsed_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

attempts = 0
while attempts < max_attempts:
	user_created_at_elapsed_minutes = fetch_user_created_at_elapsed_minutes(app_user_phone_number, api_token)
  if user_created_at_elapsed_minutes > TIME_ELAPSED_THRESHOLD_MINUTES:
  	risk_score = fetch_decision_api(app_user_phone_number, token)
	attempts = attempts + 1