Telemetry
The optional telemetry object describes the device, network and session a transaction came from. It can be added to
any transaction, whatever its account holder or counterparty type. Send it whenever your channel collects it: many
fraud and account-takeover patterns are only visible through telemetry.
Example
POST /api/transactions
Authorization: Bearer <oneview-service-account-api-key>
Content-Type: application/json
{
"transactionReference": "TXN-20260921-000901",
"direction": "OUTBOUND",
"accountHolderType": "CUSTOMER",
"paymentMethod": "NIP",
"channel": "MOBILE_APP",
"status": "POSTED",
"isCrossBorder": false,
"amount": "480000.00",
"currency": "NGN",
"executedAt": "2026-09-21T02:14:26Z",
"accountHolder": {
"customerUniqueId": "CUS-100231",
"accountNumber": "0012345678",
"accountName": "Ada Demo Okafor"
},
"counterparty": {
"counterpartyType": "EXTERNAL_BANK",
"accountName": "Demo Recipient Two",
"accountNumber": "9000000020",
"institutionCode": "999999",
"country": "NG"
},
"telemetry": {
"deviceId": "dev-7f3a9c2e51d04b88",
"deviceFingerprintHash": "dfp-3c1e9b7a0d5f4e22",
"ipAddress": "203.0.113.58",
"isVpnOrProxy": true,
"sessionId": "sess-20260921-8c41d2",
"appVersion": "5.2.1",
"country": "NGA",
"state": "Lagos",
"city": "Ikeja"
}
}
Fields
| Field | What it means | Why it matters for monitoring |
|---|---|---|
deviceId | Your stable ID for the customer's device. | Rules can count activity per device, and it can match a device on your blacklist. |
deviceFingerprintHash | A privacy-preserving fingerprint of the device, generated by your channel. | The same as deviceId, for channels that fingerprint rather than register devices. Can match your blacklist. |
ipAddress | The public IP address the request came from. | OneView looks up the IP's location for the geography risk check, rules can count activity per IP, and it can match an IP on your blacklist. |
isVpnOrProxy | Boolean: whether your channel detected a VPN or proxy. | Rules often raise the risk of large transfers made through anonymising networks. |
sessionId | The channel session, such as a web, app or USSD session. | Links several transactions made in one session. |
appVersion | The app or client version. | Rules can target outdated or unexpected app versions. |
country | Where the channel says the customer is. | Location mismatch rules. See the format rules below. |
state, city | Finer location from the channel. | Location rules and investigation. |
The example shows why telemetry matters: a large transfer at 02:14 UTC through a VPN, from a device or IP address seen on other accounts, is far easier to spot with these fields than from the amount alone.
Country format rules
telemetry.country and counterparty.country have different rules:
| Field | Accepted | Rejected |
|---|---|---|
telemetry.country | Uppercase ISO 3166-1 alpha-2 or alpha-3 codes that are assigned, such as NG, NGA, US or USA. | Lowercase (ng), unassigned codes (XX), non-ISO codes (NGR) and numeric codes (566). |
counterparty.country | ISO 3166-1 alpha-2 codes in any case, such as NG or ng. Stored in uppercase. | Alpha-3 codes (NGA) and anything that is not an assigned two-letter code. |
A rejected telemetry country returns
telemetry.country must be an uppercase ISO 3166-1 alpha-2 or alpha-3 country code. Send two-letter codes
everywhere if you want one rule that works for both fields.
Response
Telemetry does not change the response shape — this is the response to the example above:
{
"status": true,
"message": "Transaction evaluated",
"data": {
"transaction": {
"id": "7c2a9e41-3f6d-4b85-a017-9e2c0f4b3d56",
"transactionReference": "TXN-20260921-000901",
"direction": "OUTBOUND",
"receivedAt": "2026-09-21T02:14:26.705Z",
"replayed": false
},
"decision": {
"outcome": "HOLD",
"riskScore": 50,
"evaluatedAt": "2026-09-21T02:14:26.722Z",
"evaluationMs": 13.057,
"complete": true,
"rulesEvaluated": 18,
"rulesetSnapshot": "9ffa3b395a9799b1a1104ab1b536ed1667b487510829ceefc27593941fafb35e",
"gradingVersion": 3,
"triggeredRules": [
{
"ruleId": "d8790c99-5ec6-4258-8af8-9c37e11427c2",
"ruleVersion": 2,
"name": "Night-time transfer through VPN",
"action": "HOLD"
},
{
"ruleId": "4bf544b6-957d-46cf-a55b-ea89a3ff9e02",
"ruleVersion": 4,
"name": "Large outbound transfer",
"action": "FLAG"
}
]
}
}
}
This is the HOLD example from Decision responses: the VPN and night-time telemetry are
exactly what let the "Night-time transfer through VPN" rule fire. Telemetry that raises the score never appears as
its own field in the response — it only shows up indirectly, through which rules triggered.
Errors specific to telemetry
| Cause | field | code | message |
|---|---|---|---|
telemetry.country is lowercase, unassigned or numeric | telemetry.country | invalid | telemetry.country must be an uppercase ISO 3166-1 alpha-2 or alpha-3 country code |
telemetry itself is not an object | telemetry | invalid | telemetry must be an object |
telemetry has more than 64 keys | telemetry | too_large | telemetry may contain at most 64 fields |
A rejected telemetry fails the whole request, the same as any other invalid field — there is no way to submit a
transaction with telemetry dropped instead of fixed. Omit telemetry entirely if you cannot populate it correctly.
See Errors for the complete catalogue.
Keep telemetry free of secrets
Telemetry follows the same limits as accountHolder and counterparty: up to 64 keys, strings of up to 512 characters,
no arrays, and no NUL character (U+0000). Extra keys are stored as sent and shown to analysts, so never include
passwords, PINs, OTPs, CVVs, card numbers, API keys or session tokens. sessionId should be an identifier for the
session, not a token that grants access to it.