Get credit scorecard
curl --request GET \
--url https://api.dev.bsa.ai/v1/credit-scorecard/{external_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"externalId": "<string>",
"grade": "<string>",
"finalCreditScore": 123,
"finalCreditLimit": 123,
"totalOutstanding": 123,
"totalPaid": 123,
"availableCreditLimit": 123,
"executionPeriod": "<string>"
}Credit Scoring
Get credit scorecard
Fetch the current credit profile for a customer by externalId.
GET
/
v1
/
credit-scorecard
/
{external_id}
Get credit scorecard
curl --request GET \
--url https://api.dev.bsa.ai/v1/credit-scorecard/{external_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dev.bsa.ai/v1/credit-scorecard/{external_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"externalId": "<string>",
"grade": "<string>",
"finalCreditScore": 123,
"finalCreditLimit": 123,
"totalOutstanding": 123,
"totalPaid": 123,
"availableCreditLimit": 123,
"executionPeriod": "<string>"
}Returns the customer’s current credit grade, score, and pre-approved
loan limit as held by the credit scoring engine. The lookup
key is the same
Branch on
externalId you set on the customer record — so
once you’ve created a customer, scoring and lending share one
identifier.
This endpoint is read-only — it has no side effects (no SMS, no
database write).
Path parameters
string
required
The customer’s partner-supplied
externalId (the same value you sent
on POST /v1/customers). 1–128 characters; URL-encode if it contains
special characters.Example
curl -sf "$BASE/v1/credit-scorecard/partner-key-1779709585" \
-H "Authorization: Bearer $TOKEN"
Response
200 OK
{
"externalId": "partner-key-1779709585",
"grade": "C",
"finalCreditScore": 500,
"finalCreditLimit": 5000.0,
"totalOutstanding": 0.0,
"totalPaid": 0.0,
"availableCreditLimit": 5000.0,
"executionPeriod": "0.01 seconds"
}
Fields
string
Echoes the queried externalId.
string
Credit grade band. Common values:
A, B, C. Unscored customers
receive XX (see below).integer
Numeric credit score on the credit scoring scale.
number
Pre-approved ceiling in TZS as set by the scoring engine.
0 for
unscored customers. This is the raw upstream value — it doesn’t
account for any current debt.number
Sum of
summary.totalOutstanding across every loan the customer
holds in the LMS. 0 if the customer has no loans or doesn’t exist
in the LMS yet. This is a best-effort join — if the LMS is
momentarily unreachable, the field comes back as 0 rather than
failing the whole scorecard call.number
Sum of
summary.totalRepayment across every loan the customer
holds — total amount paid in over the lifetime of the customer’s
loans (principal + interest + fees + penalty). Same best-effort
semantics as totalOutstanding.number
Computed. Remaining borrowing headroom right now:
finalCreditLimit - totalOutstanding, floored at 0. Because it’s
subtractive, a customer can hold more than one loan at a time as long
as the new principal fits within what’s left; a 0 means they’re at
or over their ceiling.string
Upstream processing time. Diagnostic only — partners typically ignore it.
Unscored customers
A customer with no scoring record yet is not an error. The upstream returns200 OK with sentinel values so the USSD layer always has
something to render:
{
"externalId": "no-such-customer",
"grade": "XX",
"finalCreditScore": 100,
"finalCreditLimit": 0.0,
"totalOutstanding": 0.0,
"totalPaid": 0.0,
"availableCreditLimit": 0.0,
"executionPeriod": "0.00 seconds"
}
grade == "XX" to detect “unscored”. Use
availableCreditLimit > 0 to decide whether a new loan can be
offered — that folds in both the scoring result and the LMS debt
state in one check.
Errors
| Code | When |
|---|---|
invalid_argument | external_id path segment is empty |
unauthenticated | Token missing/invalid |
internal | Upstream credit service unavailable or returned an unhandled error |

