Skip to content

Customers API

These endpoints let a signed-in person find a customer and read everything SpeculaPro knows about them: their profile, accounts, designations, recent transactions, a 90-day activity summary and any suppressions. The Customers screens use them; this page is for scripting and for checking exactly what is returned.

Customers are sent to SpeculaPro by your systems through the ingest API, not created here. See Sending customers.

Who can call them. These endpoints are for signed-in people, not API keys. Every request is checked against the caller’s permissions, and every view of protected personal data is written to the audit log. An API key gets 401 sign in required. A person whose account setup isn’t finished (two-factor enrolment or a forced password change) gets 403 complete account setup first.

Signing in with curl. Sign in once and keep the session cookie in a file, exactly as described in Alerts and cases API: before you start:

Terminal window
export SP=https://speculapro.example.com
curl -s -c ~/.sp-cookies -H 'Content-Type: application/json' \
-d '{"workspace":"acme-pay","email":"[email protected]","password":"<your password>","totp_code":"123456"}' \
"$SP/api/v1/auth/login"

Then add -b ~/.sp-cookies to every request below.

Conventions. IDs are UUIDs. Times are RFC 3339 in UTC. Money is an integer in minor units: 495000 is GHS 4,950.00. Amounts named …_base_minor are in your workspace’s base currency.

Endpoint Does Permission Success
GET /api/v1/customers Find customers by reference or name entities.view 200
GET /api/v1/customers/{id} One customer’s full profile entities.view (+ entities.view_pii for protected fields) 200
Permission Default roles What it shows
entities.view Analyst, Senior analyst, MLRO, Rule author, Auditor Names, references, segment, risk rating, accounts (with masked identifiers), designations, transactions, activity, suppressions
entities.view_pii Senior analyst, MLRO Also the protected fields: phone, email, national ID and date of birth, decrypted

The protected fields are encrypted in the database (see Data protection). They are decrypted only for a caller with entities.view_pii, and a profile view with them decrypted writes a customer.view_pii entry to the audit log, with who looked, when and from where. To keep the log readable, repeat views of the same customer by the same person within 30 minutes (for example the page refreshing) don’t add another entry; the next view after that does.

Query parameter Meaning
q Up to 128 characters. Matches your customer reference exactly, or part of the name or reference, ignoring capitals. Empty means everyone
designated true returns only customers with an active designation (PEP, sanctioned, high risk, …)
limit 1 to 200; default 50

Results come in this order: an exact reference match first, then customers rated unacceptable, then high, then the most recently updated.

Each result:

Field Meaning
id SpeculaPro’s ID for the customer. Use it in the other endpoints
external_id Your reference for the customer
name Full name, or your reference if no name was sent
type individual or business
status As sent by your systems, for example active
segment As sent, for example retail; empty if none
risk_rating unrated, low, medium, high or unacceptable
kyc_level KYC tier as sent; left out if none
designations Types of the customer’s active designations, for example ["pep"]
open_alerts Alerts about this customer still open
active_cases Cases about this customer not yet closed
Terminal window
# By your reference
curl -s -b ~/.sp-cookies "$SP/api/v1/customers?q=CUS-004417"
# Everyone with an active designation
curl -s -b ~/.sp-cookies "$SP/api/v1/customers?designated=true&limit=200"

Returns every field from the search result, plus:

Field Meaning
country, nationality, occupation As sent; left out if none
declared_monthly_volume_minor, declared_currency The expected monthly volume from onboarding, if sent
onboarded_at When the relationship started, if sent
attributes Your custom attributes, as sent
pii The protected fields; see below
accounts Every account: id, external_id, type, provider, identifier_mask (for example +233•••••••67), currency, status, opened_at
designation_history Every designation, newest first, including revoked and expired ones. See below
transactions The most recent 50 transactions in the last 90 days
activity_90d Totals over the last 90 days of completed transactions
suppressions Suppressions whose subject is this customer, in every state, including counterparty pairs. Fields as in the Suppressions API
counterparties Who the customer dealt with most in the last 90 days, up to 20. See below
devices Devices the customer has used, most recently used first, up to 20. See below
account_events The latest account events from the last 90 days, newest first, up to 30. See below
last_transaction_at The latest completed transaction in the last 90 days; left out if none

pii

Field Meaning
visible true if you have entities.view_pii. When false, the fields below are left out
phone, email, national_id, national_id_type, date_of_birth Decrypted values, left out if not on file. date_of_birth is YYYY-MM-DD

If a value can’t be decrypted (for example after a key was rotated incorrectly), it reads [unreadable]. Tell your administrator: see Data protection.

designation_history entries: id, type, pep_class, source (manual today), reason, valid_from, valid_to, created_by and created_at, evidence (sources, reference and notes, each left out when empty; see Designations API), and for revoked ones revoked_at, revoked_by and revoke_reason. active is true while it is not revoked and inside its validity dates. created_by and revoked_by are display names.

transactions entries: id, external_id, occurred_at, direction (in or out), type, channel, status, amount_minor and currency as sent, amount_base_minor in your base currency, counterparty (name or masked identifier, if known) and flagged: true if a live rule hit this transaction.

counterparties entries, most transactions first: id (use it as counterparty_id in a counterparty-pair suppression), name (the counterparty’s name, else its masked identifier, else Unknown counterparty), identifier_mask and provider when known, count (transactions with them in the last 90 days, in any status), in_minor and out_minor (money from and to them, in base currency) and last_at (the latest transaction with them).

devices entries: id (the first 12 characters of the device’s keyed hash, the same for the same device on every customer), first_seen_at and last_seen_at (this customer’s first and latest use of it), and customers (how many customers have used it in total, this one included; more than 1 means a shared device). Devices aren’t limited to the last 90 days. Empty if your systems don’t send device_fingerprint.

account_events entries: type (such as sim_swap or otp_failed), occurred_at, and when sent, channel, success and device (the device’s 12-character code, as in devices). The other fields you send with an event are stored but not returned here.

activity_90d: in_minor and out_minor (completed money in and out, in base currency), count (completed transactions) and flagged (distinct transactions with a live rule hit on this customer).

Terminal window
curl -s -b ~/.sp-cookies "$SP/api/v1/customers/0192f3a4-5b6c-7d8e-9f01-23456789abcd"
Status Meaning Example
401 Not signed in, or called with an API key sign in required
403 Missing permission missing permission entities.view
404 No such customer in your workspace. Another workspace’s customers always look like this not found
422 Invalid parameters, such as a limit above 200 Lists each problem

How to look into a customer before deciding an alert

Section titled “How to look into a customer before deciding an alert”
  1. Find them. Search by the reference shown on the alert: GET /api/v1/customers?q=CUS-004417. Note the id.
  2. Read the profile: GET /api/v1/customers/{id}.
  3. Compare with what you expected. Is activity_90d.in_minor in line with declared_monthly_volume_minor × 3? How many of the recent transactions are flagged?
  4. Check the flags. Look at designation_history for active PEP or sanctions flags, and at suppressions for any exception already approved for this customer.
  5. Record what you found as a note on the case. See Working a case.