Transaction Monitoring: Offsite Integration
In the offsite transaction monitoring process, Shufti's clients are responsible for collecting all relevant transaction data from the end user and submitting it to Shufti for analysis and verification. This includes essential information such as transaction details, sender and recipient data, and any supporting documentation required for compliance checks. Shufti then processes this information to identify potential risks, ensuring the transaction adheres to regulatory standards and business requirements.
Additionally, Shufti supports batch verification, enabling clients to submit multiple transactions at once for review. This allows efficient, large-scale monitoring and ensures that even past transactions are screened for compliance and risk management.
Create Transaction Endpoint
Use this endpoint to submit a transaction for Transaction Trust Monitoring (TTM).
Endpoint Information
- Endpoint URL:
POST https://api.shuftipro.com/create/transaction - Content-Type:
application/json - Authentication: Basic Authentication
Authentication (Required Before Calling This Endpoint)
This endpoint uses the same authentication flow as the main API.
- Set up your Shufti account
- Get your
client_idandsecret_key - Authorize requests using Basic Auth
For complete authorization steps and examples, refer to:
Once authentication is set up, come back to this page and call the transaction endpoint below.
Prerequisites
Before sending requests to this endpoint, ensure:
- TTM (Transaction Trust Monitoring) feature is enabled for your client account
- TTM seller ID is configured for your client account
Request Example
For the full list of supported request fields and their definitions, see the Complete List of Datapoints.
{
"trans_id": "txn-87392HDK239JD",
"trans_ts": "2025-12-01T14:30:00Z",
"trans_amt": 250.75,
"trans_currency": "EUR",
"transaction_type": "Transfer",
"cust_id": "CUST9X4LM2P8",
"cust_name": "Sarah Martinez",
"cust_email": "sarah.m@example.com",
"phone": "+33612345678",
"cust_dob": "1988-03-22Z",
"cust_nationality": "French",
"cust_signup_ts": "2024-06-10T09:15:00Z",
"cust_account_balance": 8500,
"source_of_wealth": "Business Income",
"slr_ind_cat": "7995",
"slr_ind_mcc": "713290",
"slr_asp": 125.5,
"slr_crncy": "EUR",
"pmt_method": "card",
"ip": "185.45.192.78",
"device_id": "dev8k2m9n4p1q5r",
"device_score": 85,
"device_fingerprint": "FP78K9L2M3N4",
"device_reputation": "Excellent",
"platform_id": "PAYMENT-HUB-EU",
"browser_user_agent": "Mozilla 5.0 Safari 17.2",
"ba_bic": "DEUTDEFF500",
"ba_iban": "DE89370400440532013000",
"ba_name": "Sarah Martinez",
"ba_rtn_num": "026009593",
"bin_ctry": "DE",
"bin_brand": "Mastercard",
"aml_screening": {
"name": {
"full_name": "Sarah Martinez"
},
"filters": [
"Sanctions",
"PEP"
]
},
"beneficiary_id": "BEN7H9K2L4M6",
"beneficiary_name": "Michael Chen",
"beneficiary_email": "m.chen@example.com",
"beneficiary_dob": "1992-07-18Z",
"beneficiary_phone": "+8613912345678",
"beneficiary_nationality": "Chinese",
"beneficiary_ba_bic": "ICBKCNBJ110",
"beneficiary_ba_iban": "GB82WEST12345698765432",
"beneficiary_ba_name": "Michael Chen",
"beneficiary_ba_rtn_num": "121000248",
"beneficiary_bin_ctry": "CN",
"beneficiary_bin_brand": "UnionPay",
"beneficiary_aml_screening": {
"name": {
"full_name": "Michael Chen"
},
"filters": [
"Sanctions",
"Adverse Media"
]
}
}
Rule Sets
Rules you create in the Back Office Rule Builder can be grouped into rule sets. Use the optional rule_sets field to choose which rule sets a transaction is evaluated against.
| Field | Type | Required | Description |
|---|---|---|---|
| rule_sets | string[] | Optional | Names of the rule sets, as created in the Rule Builder, to evaluate the transaction against. |
{
"trans_id": "txn-87392HDK239JD",
"trans_amt": 9000,
"trans_currency": "USD",
"rule_sets": ["set_1"]
}
How rules are selected:
rule_setssent: only rules that belong to at least one of the listed rule sets are evaluated.rule_setsnot sent: only rules that are not assigned to any rule set are evaluated. Rules that belong to a rule set are skipped.
If all your rules belong to rule sets, you must send rule_sets. Otherwise no rule is evaluated and the transaction is returned as approved with no rule hits. Rule set names must match the names in the Rule Builder exactly; a name that matches no rule set is not reported as an error.
Success Response
{
"status": true,
"message": "Transaction submitted successfully",
"data": {
"transaction_id": "a2f8c9d1-3e4b-4a5c-8d7f-1b2e3a4c5d6e",
"device_id": "dev8k2m9n4p1q5r",
"score": 0.3245678901234567,
"approved": 1,
"evidence": {
"signals": [
{
"id": "7a2d9c4e",
"category": "geo",
"type": "good",
"related_to": [
"phone",
"bin_ctry",
"ip_country"
]
},
{
"id": "b3e8f1a9",
"category": "seller",
"type": "neutral",
"related_to": [
"slr_ind",
"slr_ind_cat",
"seller_id"
]
},
{
"id": "c9d4e2b7",
"category": "transaction",
"type": "good",
"related_to": [
"device_reputation",
"device_score"
]
},
{
"id": "d1f5a8c3",
"category": "transaction",
"type": "neutral",
"related_to": [
"ip"
]
},
{
"id": "e4b2c9d6",
"category": "transaction",
"type": "good",
"related_to": [
"trans_amt"
]
},
{
"id": "f8a3d1e7",
"category": "user",
"type": "good",
"related_to": [
"cust_email",
"cust_account_balance"
]
}
]
},
"rule_hits": {
"decisive_hit": null,
"all": []
},
"validation": {
"ok": true
},
"sanctions_lists": {
"hit": "NO_HIT"
},
"aml_screening": {
"hit": "NO_MATCH"
}
}
}
Risk Assessment Interpretation
- Score Range:
0.0(lowest risk) to1.0(highest risk) - Approval Status:
0= Transaction declined1= Transaction approved2= Transaction manual review3= Transaction custom action (when rule hits with custom action)
To find out why a transaction was declined or sent for review, see Declined Reasons.
Response Fields Description
Root Level
| Field | Type | Description |
|---|---|---|
| status | boolean | Indicates whether the request was successful. |
| message | string | Human-readable status message. |
| data | object | Contains detailed transaction analysis results. |
Data Object
| Field | Type | Description |
|---|---|---|
| transaction_id | string | Unique transaction identifier: 32 hexadecimal characters in the 8-4-4-4-12 pattern (for example 9547783a-85a8-1dcd-5e7a-514a0fc1de56). It looks like a UUID but is not an RFC 4122 UUID, so don't validate it as one or store it in a UUID-typed column. Use it to find the transaction in the Back Office. |
| device_id | string | Processed device identifier. Returned when enabled for your account. |
| score | number | Fraud risk score from 0 to 1 (lower is better). |
| approved | integer | Decision for the transaction: 0 declined, 1 approved, 2 manual review, 3 custom action. See Risk Assessment Interpretation. |
| evidence | object | Evidence signals that influenced the score. |
| rule_hits | object | Information about triggered rules. |
| validation | object | Validation status and errors (if any). |
| sanctions_lists | object | Sanctions screening result. Returned when enabled for your account. |
| aml_screening | object | AML screening result for the customer. Returned when enabled for your account and aml_screening was sent in the request. |
Evidence Object
| Field | Type | Description |
|---|---|---|
| signals | array | Array of signal objects indicating risk factors. |
Signal Object
| Field | Type | Description |
|---|---|---|
| id | string | Unique signal identifier. |
| category | string | Signal category (for example: geo, transaction, user, seller). |
| type | string | Signal type: good, bad, or neutral. |
| related_to | array/null | Field names associated with this signal. |
Rule Hits Object
| Field | Type | Description |
|---|---|---|
| decisive_hit | object/null | Rule that determined outcome; null when none applies. |
| all | array | Array of all rules that were triggered. |
Rule Object (inside decisive_hit or all)
| Field | Type | Description |
|---|---|---|
| id | string | Unique rule identifier (UUID). |
| short_id | integer | Short numeric identifier of the rule. |
| version | integer | Rule version number. |
| action | string | Rule action (for example: reject, accept, review). |
| rule_name | string | Human-readable rule name. |
Validation Object
| Field | Type | Description |
|---|---|---|
| ok | boolean | Indicates whether validation passed completely. |
| errors | array | Validation errors (present only when ok is false). |
Validation Error Object
| Field | Type | Description |
|---|---|---|
| datapoint | string | Name of the field with validation issue. |
| message | string | Validation error detail. |
Sanctions Lists Object
| Field | Type | Description |
|---|---|---|
| hit | string | Possible values: HIT, NO_HIT, ERROR. |
AML Screening Object
| Field | Type | Description |
|---|---|---|
| hit | string | Possible values: MATCH, POTENTIAL_MATCH, NO_MATCH, ERROR. |
Error Responses
Errors come back in one of two body shapes, depending on where the request was rejected:
- Request errors (400 validation, 401 authentication, 429 rate limit) are returned before the transaction is processed. For 400 and 401 the body has an
eventand anerrorobject withkey(the field at fault, when there is one) andmessage; only the first validation error is returned. For 429 the samekeyandmessagefields are at the top level of the body. - Processing errors (403, 404, 4xx rejections from the screening engine, 500) are returned with
status: false, amessage, and, except for 403, anerrorstring with the reason.
Validation Error (HTTP 400)
Returned when a field is missing or has an invalid format. error.key names the field.
{
"event": "request.invalid",
"error": {
"service": "",
"key": "trans_id",
"message": "Transaction ID is required"
},
"email": null,
"country": null
}
Unauthorized (HTTP 401)
Returned when the Basic Auth credentials are missing or invalid.
{
"event": "request.unauthorized",
"error": {
"service": "",
"key": "",
"message": "Authorization keys are invalid/missing."
},
"email": null,
"country": null
}
Forbidden (HTTP 403)
Returned when Transaction Trust Monitoring is not enabled for your account.
{
"status": false,
"message": "KYT feature is not enabled for your account"
}
Account Not Configured (HTTP 404)
Returned when TTM is enabled but your account has not been fully configured for it yet. Contact Shufti support.
{
"status": false,
"message": "An error occurred while processing transaction submission",
"error": "Account not configured for this client"
}
Rejected by the Screening Engine (HTTP 4xx)
Returned when the request passes validation but the screening engine rejects it. The HTTP status is the one the engine returned (usually 400 or 422), and error starts with Validation failed: followed by the engine's reason.
{
"status": false,
"message": "An error occurred while processing transaction submission",
"error": "Validation failed: <reason>"
}
Too Many Requests (HTTP 429)
Returned when you send more than 100 requests per minute. Wait for the number of seconds in the Retry-After response header before retrying. The X-RateLimit-Limit and X-RateLimit-Remaining headers show your limit and how many requests are left in the current window.
{
"service": "",
"key": "",
"message": "Too Many Attempts."
}
Server Error (HTTP 500)
Returned when the transaction could not be processed because of an internal error. Retry the request later.
{
"status": false,
"message": "An error occurred while processing transaction submission",
"error": "API server error"
}
HTTP Status Codes
| Status Code | Description | Body shape |
|---|---|---|
| 200 | Transaction submitted and screened. | Success response |
| 400 | A field is missing or invalid (event: request.invalid), or the screening engine rejected the request (error: "Validation failed: ..."). | Request error / Processing error |
| 401 | Authentication failed; Basic Auth credentials are missing or invalid. | Request error |
| 403 | Transaction Trust Monitoring is not enabled for your account. | Processing error |
| 404 | Your account is not configured for Transaction Trust Monitoring. | Processing error |
| 422 | The screening engine rejected the request (error: "Validation failed: ..."). | Processing error |
| 429 | Rate limit exceeded (100 requests per minute). Retry after Retry-After seconds. | Request error |
| 500 | Internal server error. | Processing error |
Fetch a Filed Regulatory Report
Use this endpoint to read back a regulatory report your compliance team has signed off or filed in the Back Office, so you can submit it to your reporting authority from your own systems instead of downloading it manually.
This endpoint currently supports FINTRAC (Canada) reports only. Support for other jurisdictions will be added over time.
Endpoint Information
- Endpoint URL:
POST https://api.shuftipro.com/regulatory-report/detail - Content-Type:
application/json - Authentication: Basic Authentication (same
client_id/secret_keyas above) - Rate limit: 100 requests per minute
Prerequisites
- TTM (Transaction Trust Monitoring) feature is enabled for your client account
- The report has been signed off for filing or already filed in the Back Office. Reports still in Draft, Assigned to MLRO, or Returned to Analyst are not retrievable through this endpoint.
Request Example
{
"reference": "RR-CA-2026-00001",
"version": 2
}
| Field | Type | Required | Description |
|---|---|---|---|
| reference | string | Required | The report's reference, as shown in the Back Office. Up to 50 characters. |
| version | integer | Optional | A specific version of the report, for when it has been corrected and refiled. Omit it to get the latest version that is signed off or filed — a newer correction still in draft never hides the version you can already act on. |
Success Response
{
"error": false,
"status": "SUCCESS",
"message": "Report fetched successfully",
"data": {
"reference": "RR-CA-2026-00001",
"version": 2,
"authority": "FINTRAC",
"jurisdiction_code": "ca",
"report_type": "STR",
"status": "ready_to_file",
"signed_off_at": "2026-10-20T09:15:00+00:00",
"filed_at": null,
"regulator_reference": null,
"reporting_entity": {
"filing_institution": "Example Payments Inc.",
"reporter_code": "RPT-00482",
"compliance_officer_code": "CO-1029",
"service_provider_category": "MSB"
},
"subject": {
"name": "Michael Chen",
"customer_id": "CUST9X4LM2P8"
},
"amount": {
"amount": 12000,
"currency": "CAD",
"original_amount": 12000,
"original_currency": "CAD",
"converted_amount": null,
"converted_currency": null,
"exchange_rate": null,
"exchange_rate_date": null
},
"fields": {
"narrative": "...",
"suspicious_activity_indicators": ["..."]
},
"created_at": "2026-10-18T12:00:00+00:00",
"updated_at": "2026-10-20T09:15:00+00:00"
}
}
Response Fields Description
| Field | Type | Description |
|---|---|---|
| reference | string | The report's reference. |
| version | integer | The version returned. |
| authority | string | The regulator the report is filed with (FINTRAC for Canada). |
| jurisdiction_code | string | ISO country code of the filing jurisdiction (ca). |
| report_type | string | The type of report, for example STR. |
| status | string | ready_to_file (signed off, not yet filed — shown as "Ready to Download" in the Back Office) or filed. |
| signed_off_at | string/null | ISO 8601 timestamp of MLRO sign-off. |
| filed_at | string/null | ISO 8601 timestamp the report was filed with the regulator, null until then. |
| regulator_reference | string/null | The regulator's own reference for the filing, once available. |
| reporting_entity | object | Your registered filing details. See Reporting Entity Object. |
| subject | object | The customer the report concerns. See Subject Object. |
| amount | object | The transaction amount and, where applicable, the currency conversion used. See Amount Object. |
| fields | object | The report's own answers, keyed by the Back Office's FINTRAC field IDs — not yet shaped to FINTRAC's own schema. |
| created_at | string | ISO 8601 timestamp the report was created. |
| updated_at | string | ISO 8601 timestamp of the last change to the report. |
Reporting Entity Object
| Field | Type | Description |
|---|---|---|
| filing_institution | string/null | Your institution's registered filing name. |
| reporter_code | string/null | Your registered reporter code with the regulator. |
| compliance_officer_code | string/null | Your registered compliance officer code. |
| service_provider_category | string/null | Your registered service provider category (for example MSB). |
Subject Object
| Field | Type | Description |
|---|---|---|
| name | string/null | The name of the customer the report concerns. |
| customer_id | string/null | Your cust_id for this customer, as sent on the originating transaction. |
Amount Object
| Field | Type | Description |
|---|---|---|
| amount | number | The primary amount reported, in currency. |
| currency | string | The currency amount is in. |
| original_amount | number/null | The transaction's original amount, before conversion. |
| original_currency | string/null | The transaction's original currency. |
| converted_amount | number/null | The converted amount, when a currency conversion applies; null otherwise. |
| converted_currency | string/null | The currency converted_amount is in. |
| exchange_rate | number/null | The exchange rate used for the conversion. |
| exchange_rate_date | string/null | ISO 8601 date the exchange rate was taken. |
Error Responses
Unauthorized (HTTP 401)
Returned when the Basic Auth credentials are missing or invalid.
{
"error": true,
"status": "ERROR",
"message": "Authorization keys are invalid/missing."
}
Forbidden (HTTP 403)
Returned when Transaction Trust Monitoring is not enabled for your account.
{
"error": true,
"status": "ERROR",
"message": "Transaction monitoring is not active for your account, kindly get in touch with your POC for further assistance"
}
Validation Error (HTTP 422)
Returned when reference is missing or too long, or version is not a positive integer.
{
"error": true,
"status": "ERROR",
"message": "reference is required"
}
Not Found (HTTP 404)
Returned when no report with that reference (and version, if given) belongs to your account and is signed off or filed. This includes reports that exist but are still in Draft, Assigned to MLRO, or Returned to Analyst.
{
"error": true,
"status": "ERROR",
"message": "Report not found, or not yet signed off for filing"
}
Too Many Requests (HTTP 429)
Returned when you send more than 100 requests per minute. Wait for the number of seconds in the Retry-After response header before retrying.
Server Error (HTTP 500)
{
"error": true,
"status": "ERROR",
"message": "An internal error occurred. Please try again later."
}
HTTP Status Codes
| Status Code | Description |
|---|---|
| 200 | Report found and returned. |
| 401 | Authentication failed; Basic Auth credentials are missing or invalid. |
| 403 | Transaction Trust Monitoring is not enabled for your account. |
| 404 | No matching report found, or it is not yet signed off for filing. |
| 422 | reference or version is missing or invalid. |
| 429 | Rate limit exceeded (100 requests per minute). |
| 500 | Internal server error. |