Credit Scoring Guide
D-ME integrates Skorix AI credit scoring into the verification flow. Add a single flag to your verification request and receive a pseudonymised credit score alongside the identity result — no extra API call needed at verification time.
How scoring works
- Add
"score_requested": trueto your verification request - After Smile Identity confirms the identity, D-ME extracts pseudonymised behavioural features
- These features are sent to the Skorix scoring engine (no PII — see below)
- The score (0–1000) is attached to the verification and included in the webhook
- Retrieve the score anytime via
POST /score/get
Requesting a score
Add score_requested=true to your verification request. Your API key must have the score.get scope.
curl -X POST https://api.d-id.me/api/v1/kyc/verify \
-H "Authorization: Bearer dme_live_xxxx" \
-F "id_type=national_id" \
-F "country=SN" \
-F "external_ref=user_001" \
-F "score_requested=true" \
-F "front_image=@id_front.jpg" \
-F "selfie_image=@selfie.jpg"Retrieve a score
After verification completes, retrieve the score using the verification ID:
curl -X POST https://api.d-id.me/api/v1/score/get \
-H "Authorization: Bearer dme_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"verificationId": "550e8400-e29b-41d4-a716-446655440000"}'{
"data": {
"scoreId": "sk_7f3a9c2d-...",
"score": 742,
"band": "high",
"bandDescription": "Good profile. Suitable for most credit products.",
"confidence": 0.95,
"modelVersion": "mock-v1.0.0",
"computedAt": "2026-05-06T10:30:25Z",
"featuresUsed": [
"document_authenticity_score",
"liveness_score",
"country_risk_band",
"id_type_weight",
"age_band",
"verification_timestamp",
"day_of_week",
"hour_of_day"
],
"flags": []
}
}Score fields
| Field | Type | Description |
|---|---|---|
score | integer | 0–1000 composite score |
band | string | low / medium / high / premium |
bandDescription | string | Human-readable band explanation |
confidence | float | Model confidence, 0.0–1.0 |
modelVersion | string | Skorix model version used |
featuresUsed | string[] | Feature names used (no values) |
flags | string[] | Risk flags (empty in most cases) |
Score bands
| Band | Range | Description | Recommended Use |
|---|---|---|---|
premium | 800–1000 | Excellent profile | Premium credit products, highest limits |
high | 550–799 | Good profile | Most credit products |
medium | 300–549 | Moderate risk | Standard products, lower limits |
low | 0–299 | Higher risk | Manual review recommended |
Score in the webhook
The verification.completed webhook includes the score object:
{
"event": "verification.completed",
"data": {
"verificationId": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"externalRef": "user_001",
"completedAt": "2026-05-06T10:30:25Z",
"livenessCheckPassed": true,
"documentVerified": true,
"score": {
"id": "local-score-uuid",
"score": 742,
"band": "high",
"bandDescription": "Good profile. Suitable for most credit products.",
"confidence": 0.95
}
},
"timestamp": "2026-05-06T10:30:26Z"
}The score field is null when scoring was not requested or failed. Always handle the null case gracefully:
Handling scores in your application
// Always handle null score — scoring can fail without failing verification
function handleVerification(result) {
if (!result.score) {
// Verification succeeded but score unavailable
// Option 1: approve with manual review
// Option 2: request score separately via POST /score/get
console.log('Score unavailable, proceeding without scoring');
return { decision: 'manual_review', reason: 'scoring_unavailable' };
}
const { score, band, confidence } = result.score;
// Low confidence → manual review
if (confidence < 0.70) return { decision: 'manual_review', reason: 'low_confidence' };
// Band-based decision
if (band === 'premium') return { decision: 'approve', limit: 5_000_000 }; // XOF
if (band === 'high') return { decision: 'approve', limit: 2_000_000 };
if (band === 'medium') return { decision: 'approve', limit: 500_000 };
if (band === 'low') return { decision: 'manual_review', reason: 'low_band' };
return { decision: 'decline', reason: 'insufficient_score' };
}Feature pseudonymisation
The following signals are derived from the identity verification result and sent to Skorix. No PII is ever transmitted.
- document_authenticity_score — derived from Smile Identity result code (0.0–1.0)
- liveness_score — liveness check pass/fail → numeric (0.0–1.0)
- country_risk_band — country-level risk category (SN=medium, MA=low)
- id_type_weight — reliability weight by document type (passport=1.0, national_id=0.9)
- age_band — statistical default, not derived from raw DOB
- verification_timestamp / day_of_week / hour_of_day — timing signals
When scoring fails
Scoring failure never fails or delays the verification. If Skorix is unavailable, the verification completes with score: null and the verification metadata includes:
"metadata": {
"scoring_skipped": true,
"scoring_error": "UNAVAILABLE"
}You can retry scoring separately using POST /score/get with the verification ID once the service recovers.
Sandbox scores
In sandbox mode, D-ME uses the mock Skorix API which produces deterministic scores based on input features. The same verification input always returns the same score — making sandbox tests reproducible. Sandbox calls are never billed.
Pricing
Each successful POST /score/get call generates a metered usage event of type score.get. See Billing docs for pricing. Sandbox score requests are free.