Risk Decline Override

Overview

Trustly's Risk Decline Override is the dedicated solution for overriding Trustly decisions on transaction approvals. This service allows you to approve capture transactions that Trustly has declined based on its risk analysis turning it to a non-guaranteed capture, providing the flexibility to manage risk according to your own criteria so you can have the functionalities of guaranteed and non-guaranteed payment combined on a single product.

Features

  • Trustly Integration: Direct integration with Trustly's payment system.
  • Risk Data Access: Retrieve detailed risk data for transactions.
  • Custom Risk Management: Make decisions based on your own risk appetite and policies.
  • Override Capability: Approve transactions that Trustly has flagged for potential override, making them non-guaranteed.

Integration

By integrating Trustly Decline Transaction Override, you can effectively manage your transaction approvals, ensuring that you maintain control over your financial risk while utilizing the strengths of Trustly's risk analysis.

  1. Receive Trustly's declined/failed transaction notification with the extended reason codes and a flag that indicates if the transaction override is possible.
  2. If the override is possible, call the Get Risk Data API to get risk data from Trustly to make a decision on whether to approve or not the transaction.
  3. If your risk assessment result is to approve the transaction call the Approve Transaction API to override Trustly's risk decline turning the transaction into a non-guaranteed transaction.
  4. Handle returned transactions for the non-guaranteed transactions. Trustly also offers a collection Representment as a service product that can be enabled for the non-guaranteed transaction returns to reduce the losses.

API Reference

1. Receive Decline Capture Transaction Notification from Trustly

When Trustly denies a transaction, they will send a notification containing the following details:

  • merchantId (string): Unique identifier for the merchant.
  • merchantReference (string): Unique transaction identifier.
  • paymentType (string): Type of payment.
  • transactionType (string): Type of transaction.
  • eventId (string): Unique identifier for the event.
  • eventType (string): Type of event, e.g., "Deny".
  • objectId (string): Unique identifier for the object.
  • objectType (string): Type of object, e.g., "Transaction".
  • message (string): Message describing the reason for denial.
  • timeZone (string): Time zone of the event.
  • createdAt (string): Timestamp of the event.
  • errorCode (string): Error code for the denial.
  • isOverridePossible (boolean): If transaction override is possible.
  • shouldOverrideBeAvoided (boolean): If transaction override should be avoided (due to the extended reasons provided).
  • paymentProviderTransaction.reasonCode (string): Reason code from the payment provider.
  • paymentProviderTransaction.reasonCodeMessage (string): Message corresponding to the reason code.
  • paymentProviderTransaction.status (string): Status of the transaction from the payment provider.
  • paymentProviderTransaction.statusMessage (string): Status message from the payment provider.
  • paymentProviderTransaction.extendedReason.code (repeated string): Extended reason codes.
  • status (string): Status of the transaction.
  • statusMessage (string): Message corresponding to the transaction status.

Sample Notification Request:

POST /{notification path}
Authorization: Basic TThSYUhnRWpCRTU0enVGWU1SUXE6RVlOM0dYYXNyVlUxdlExdXlZejIyTk5RZHk0PQ==
merchantId=00123&merchantReference=my+reference&paymentType=2&transactionType=3&eventId=1030845856&eventType=Deny&objectId=1025228290&objectType=Transaction&message=Not+enough+balance&createdAt=1714503865362&errorCode=331&isOverridePossible=true&shouldOverrideBeAvoided=true&paymentProviderTransaction.reasonCode=12&paymentProviderTransaction.reasonCodeMessage=Not+enough+balance&paymentProviderTransaction.status=SW021&paymentProviderTransaction.statusMessage=Not+enough+balance&paymentProviderTransaction.extendedReason.code=10000&paymentProviderTransaction.extendedReason.code=11000&status=8&statusMessage=Denied

Please refer to Payment Decline Codes and Reason Codes (link) for more information on decline reason codes shared by Trustly.

2. Get Risk Data

Endpoint: /api/v1/transactions/{transactionId}/risk

Method: GET

Description: Retrieves risk data for the specified declined capture transaction.

Request Parameters:

  • transactionId (string): Unique identifier for the transaction.

Sample Request:

GET /api/v1/transactions/1006755981/risk
Host: trustly.one
Authorization: Basic TThSYUhnRWpCRTU0enVGWU1SUXE6RVlOM0dYYXNyVlUxdlExdXlZejIyTk5RZHk0PQ==

Response:

  • responseCode (string): Response code for the risk data request.
  • reasonCode (integer): Reason code for the transaction denial.
  • isOverridePossible (boolean): Indicates if the override is possible.
  • shouldOverrideBeAvoided (boolean): Indicates if the override should be avoided.
  • extendedReasons (array): Detailed reasons for the transaction denial.
  • hasEnoughBalance (optional boolean): Indicates if there is enough balance on the bank account to pay for the capture transaction. The balance on the bank account must be enough to pay this transaction on the settlement date considering all pending ACH transactions for the user that are still pending settlement (such as non processed or non settled payments across all Trustly's merchants) including predicted future deposits on the account (such as W2 income).
  • suggestedRetryAmount (optional string): Suggested retry amount for the transaction.
  • velocity (optional array): Array of velocity objects detailing transaction activity.
    • period (integer): Period in days.
    • customer (object): Customer transaction activity.
      • captures (integer): Number of captures.
      • deposits (integer): Number of deposits.
    • device (object): Device transaction activity.
      • captures (integer): Number of captures.
      • deposits (integer): Number of deposits.
    • account (object): Account transaction activity.
      • captures (integer): Number of captures.
      • deposits (integer): Number of deposits.
    • overall (object): Overall transaction activity.
      • captures (integer): Number of captures.
      • deposits (integer): Number of deposits.
  • predictedReturnRisk (optional object): Predicted return risk data, which includes:
    • Customer-Initiated Return Risk: This corresponds to the risk of payment returns initiated by customers, such as unauthorized ACH returns, stop payment ACH returns, and frozen account ACH returns.
      • minRate (integer): Minimum return rate (in basis points).
      • maxRate (integer): Maximum return rate (in basis points).
    • Bank-Initiated Return Risk: This corresponds to the risk of payment returns initiated by financial institutions, including NSFs and administrative returns.
      • minRate (integer): Minimum return rate (in basis points).
      • maxRate (integer): Maximum return rate (in basis points).
    • Combined Return Risk: This combines both customer-initiated and bank-initiated risks to provide an overall return risk assessment.
      • minRate (integer): Combined minimum return rate (in basis points).
      • maxRate (integer): Combined maximum return rate (in basis points).

Sample Response:

{
  "responseCode": "SW021",
  "reasonCode": 1,
  "isOverridePossible": true,
  "shouldOverrideBeAvoided": false,
  "extendedReasons": [
    {
      "code": 10000,
      "description": "Exceeded thresholds"
    },
    {
      "code": 11072,
      "description": "Exceeded 72 hours consumer amount velocity limit"
    }
  ],
  "hasEnoughBalance": true,
  "suggestedRetryAmount": "230.00",
  "velocity": [
    {
      "period": 30,
      "customer": {
        "captures": 2,
        "deposits": 3
      },
      "device": {
        "captures": 3,
        "deposits": 4
      },
      "account": {
        "captures": 4,
        "deposits": 5
      },
      "overall": {
        "captures": 4,
        "deposits": 5
      }
    },
    {
      "period": 90,
      "customer": {
        "captures": 3,
        "deposits": 3
      },
        "device": {
        "captures": 3,
        "deposits": 4
      },
      "account": {
        "captures": 4,
        "deposits": 5
      },
      "overall": {
        "captures": 4,
        "deposits": 5
      }
    }
  ],
  "predictedReturnRisk": {
    "customerInitiated": {
      "minRate": 0,
      "maxRate": 50
    },
    "bankInitiated": {
      "minRate": 100,
      "maxRate": 300
    },
    "minRate": 100,
    "maxRate": 350
  }
}

Please refer to Payment Decline Codes and Reason Codes (link) for more information on decline reason codes shared by Trustly.

3. Approve Transaction

Endpoint: /api/v1/transactions/{transactionId}/approve

Method: POST

Description: Approves the specified transaction, bypassing/overriding Trustly's risk engine turning it on a non-guaranteed transaction. In case a return happens for the resulting non-guaranteed transaction its status changes to Reversed and the payment provider transaction status shows the return code (such as R03).

Request Parameters:

  • transactionId (string): Unique identifier for the transaction.

Sample Request:

POST /api/v1/transactions/1006755981/approve
Host: trustly.one
Authorization: Basic TThSYUhnRWpCRTU0enVGWU1SUXE6RVlOM0dYYXNyVlUxdlExdXlZejIyTk5RZHk0PQ==

Response:

  • transaction (object): The updated transaction object, including status.

Sample Response:

{
    "transaction": {
        "transactionId": "1025319672",
        "transactionType": 3,
        "originalTransactionId": "1025319406",
        "payment": {
            "paymentId": "1024188827",
            "paymentType": 2,
            "system": 1,
            "country": "US",
            "merchant": {
                "merchantId": "1076"
            },
            "merchantReference": "A8791F6165148D27",
            "merchantId": "1076",
            "customer": {
                "customerId": "1024101150"
            },
            "fingerprint": "ICaCEX7AjYCt14TvsQp6DBwi8T8=",
            "verification": {
                "status": 3,
                "mode": 3,
                "verifyCustomer": false
            },
            "account": {
                "name": "Demo Checking Account",
                "type": 1,
                "profile": 1,
                "country": "US",
                "accountNumber": "6576",
                "routingNumber": "124003116",
                "verified": true,
                "verification": {
                    "verified": true,
                    "type": 2,
                    "hasEnoughFunds": false
                },
                "source": 1,
                "virtualAccountRoutingPair": false
            },
            "description": "Globex Demo",
            "currency": "USD",
            "amount": "0.00",
            "paymentProvider": {
                "paymentProviderId": "200005501",
                "type": 1,
                "subtype": 1000,
                "name": "Demo Bank",
                "country": "US"
            },
            "paymentProviderSubtype": 1000,
            "auth": {
                "token": "1B8F4NF3O086",
                "status": 2,
                "message": "Authorized"
            },
            "authorization": "1B8F4NF3O086",
            "authorizationStatus": 2,
            "authorizationStatusMessage": "Authorized",
            "pending": "0.00",
            "paid": "2.00",
            "refunded": "0.00",
            "reversed": "0.00",
            "balance": "2.00",
            "createdAt": 1719836931223,
            "updatedAt": 1719851444167,
            "recordVersion": 10,
            "paymentFlow": 79,
            "allowedPaymentProviderSubType": [
                1000,
                2000
            ]
        },
        "currency": "USD",
        "amount": "1.00",
        "pending": "0.00",
        "paid": "1.00",
        "refunded": "0.00",
        "reversed": "0.00",
        "balance": "1.00",
        "paymentProviderTransaction": {
            "paymentProviderTransactionId": "ptx-fBQgeemdGzcWSE0QxqA60G8M-sbx",
            "signature": "46401",
            "status": 118,
            "statusMessage": "Settled",
            "paymentProcessor": {
                "paymentProcessorId": "100000016"
            },
            "instantSettle": false,
            "statementId": "1K8T",
            "reasonCode": -1
        },
        "status": 4,
        "statusMessage": "Completed",
        "ip": "177.53.170.106",
        "createdAt": 1719851400859,
        "processedAt": 1719851443780,
        "completedAt": 1719851444167,
        "updatedAt": 1719851444172,
        "ppTrxId": "ptx-fBQgeemdGzcWSE0QxqA60G8M-sbx",
        "merchantReference": "A8791F6165148D27",
        "automaticRepresentment": false,
        "paymentProcessorType": "ACH",
        "statusCode": "AC118",
        "forgiven": "0.00",
        "kycType": -1,
        "recordVersion": 7
    }
}

4. Receive ACH Return Notification from Trustly

When an ACH return happens on a transaction whose risk decline from Trustly was overridden, the resulting non-guaranteed transaction has its status changed to Reversed and the payment provider transaction status shows the ACH return code (e.g. R01). Additionally, Trustly places a hold on the consumer so all their subsequent transactions are automatically declined. In order to be possible for the consumer to authorize new transactions, you must call the Remove Debt Block API.

Trustly sends webhook notifications to make you aware of ACH returns. These notifications include the following details about the status change:

  • merchantId (string): Unique identifier for the merchant.
  • merchantReference (string): Unique transaction identifier.
  • paymentType (string): Type of payment.
  • transactionType (string): Type of transaction.
  • eventId (string): Unique identifier for the event.
  • eventType (string): Type of event, e.g., "Reverse".
  • objectId (string): Unique identifier for the object.
  • objectType (string): Type of object, e.g., "Transaction".
  • message (string): Message describing the reason for reversal.
  • timeZone (string): Time zone of the event.
  • createdAt (string): Timestamp of the event.
  • paymentProviderTransaction.status (string): Status of the transaction from the payment provider.
  • paymentProviderTransaction.statusMessage (string): Status message from the payment provider.
  • reversedAmount (string): The reversed amount.
  • status (string): Status of the transaction.
  • statusMessage (string): Message corresponding to the transaction status.

Sample Notification Request:

POST /{notification path}
Authorization: Basic TThSYUhnRWpCRTU0enVGWU1SUXE6RVlOM0dYYXNyVlUxdlExdXlZejIyTk5RZHk0PQ==
merchantId=00123&merchantReference=my+reference&paymentType=2&transactionType=3&eventId=1030845856&eventType=Reverse&objectId=1025228290&objectType=Transaction&message=US_ACH_CROSSRIVER+returned+transaction+with+message%3A+R01&createdAt=1714503865362&paymentProviderTransaction.status=R01&paymentProviderTransaction.statusMessage=Insufficient+Funds&reversedAmount=37.99&status=10&statusMessage=Reversed

5. Remove Debt Block

Endpoint: /api/v1/transactions/{transactionId}/removeDebtBlock

Method: POST

Description: Removes any holds that may have been placed by Trustly on the consumer due to an ACH return on an overridden transaction. If there are no other transactions with debt blocks, the consumer will be able to successfully authorize new transactions.

Request Parameters:

  • transactionId (string): Unique identifier for the transaction that has received an ACH return.

Sample Request:

POST /api/v1/transactions/1006755981/removeDebtBlock
Host: trustly.one
Authorization: Basic TThSYUhnRWpCRTU0enVGWU1SUXE6RVlOM0dYYXNyVlUxdlExdXlZejIyTk5RZHk0PQ==

Response:

  • An empty object.

Sample Response:

{}