Connect

Connect allows you to create a connected graph of your customers using common attributes such as emails, phone numbers, device IDs or payment methods to link them together. The graph can be enhanced to show additional information about customers such as receipt of chargebacks or manual reviews. Customers can be ’tagged’ (for example, as a VIP), and the presence of this tag can be searched for. The results are available immediately in the Connect dashboard for analysis, and can be consumed as features through the API for use within your own systems.

Connecting Customers

To add a customer to Connect you will need to send the customer’s details to the Connect Endpoint.

If you add another customer that shares some attributes with the original customer, Connect will link them together.

Customers can be connected or linked together by sharing a number of different common attributes:

Connect by Email

To add the first customer with an email address, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_1111111",
        "email": "john.smith@gmail.com"
    },
    "timestamp": 1486387634000
}

To add the second customer with the same email address, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_2222222",
        "email": "john.smith@gmail.com"
    },
    "timestamp": 1486387634000
}

Connect by Telephone

To add the first customer with a telephone number, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_1111111",
        "telephone": "+441234567890",
        "telephoneCountry": "GB"
    },
    "timestamp": 1486387634000
}

To add the second customer with the same telephone number, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_2222222",
        "telephone": "+441234567890",
        "telephoneCountry": "GB"
    },
    "timestamp": 1486387634000
}

Connect by Device ID

To add the first customer with a device ID, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_1111111"
    },
    "device": {
        "deviceId": "dv_1234567890"
    },
    "timestamp": 1486387634000
}

To add the second customer with the same device ID, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_2222222"
    },
    "device": {
        "deviceId": "dv_1234567890"
    },
    "timestamp": 1486387634000
}

Connect by Payment Method

To add the first customer with a payment method, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_1111111"
    },
    "paymentMethods": [
        {
            "card": {
                "cardLastFour": "1234",
                "cardType": "visa",
                "expiryMonth": 4,
                "expiryYear": 2020,
                "instrumentId": "in_1234567890"
            }
        }
    ],
    "timestamp": 1486387634000
}

To add the second customer with the same payment method, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_2222222"
    },
    "paymentMethods": [
        {
            "card": {
                "cardLastFour": "1234",
                "cardType": "visa",
                "expiryMonth": 4,
                "expiryYear": 2020,
                "instrumentId": "in_1234567890"
            }
        }
    ],
    "timestamp": 1486387634000
}

Adding Disputes

You are also able to submit dispute information for customers. If customers within the same network have disputed payments, this is often an indicator of an organised ring of fraudsters. By adding disputes to a customer, they can be associated with other customers via the graph links.

See Ravelin’s guide to disputes to learn more.

Customer with a Dispute

To add a dispute for a new or existing customer, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customerId": "cust_1111111",
    "dispute": {
        "amount": 373,
        "currency": "GBP",
        "disputeId": "ch_8_5a8d1bea-6d38-11e7-8f2c-9801a79b5e51",
        "reason": "fraud",
        "stage": "CHARGEBACK"
    },
    "timestamp": 1486387634000
}

Reviewing Customers

You are also able review customers to specify your personal impression on their trustworthiness. This may be as a result of manual investigation or additional information (such as being your staff). You can review customers to be one of 3 different statuses.

  • UNREVIEWED
  • GENUINE
  • FRAUDSTER

Fraudulent Customer

To review a customer as a fraudster, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customerId": "cust_1111111",
    "review": {
        "comment": "Excessive chargebacks received",
        "label": "FRAUDSTER",
        "reviewer": {
            "email": "terry.support@mycompany.com",
            "name": "Terry Support"
        }
    },
    "timestamp": 1486387634000
}

Genuine Customer

To review a customer as genuine, the request looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customerId": "cust_2222222",
    "review": {
        "comment": "Corporate staff account",
        "label": "GENUINE",
        "reviewer": {
            "email": "terry.support@mycompany.com",
            "name": "Terry Support"
        }
    },
    "timestamp": 1486387634000
}

Tagging Customers

Customers can be tagged with strings such as vip, or politically-exposed-person. You can then query for the presence of this tag in the network, and the depth away from the target customer.

Setting/Unsetting a Tag

To tag a customer, specify the tag ID followed by true or alternatively false to unset it. Different tags can set be set/unset in the same request which looks like this:

POST https://api.ravelin.com/v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customer": {
        "customerId": "cust_2222222",
        "tags": {
          "ex-staff": true,
          "staff": false
        }
    },
    "timestamp": 1486387634000
}

Querying a Graph for Tags

You can query for the presence of a particular tag in a network. The response will contain any customers that contain that tag, and their distance from the target customer. If the target customer also has the queried tag, they will be returned in the response with “depth”: 0. The request and response look like this for a customer that does not have the tag but is in a network with other customers who have the tag:

GET /v2/connect/tag?customerId=cust_1111111&depth=10&tagId=vip HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "matches": [
        {
            "customerId": "cust_2222222",
            "depth": 2
        },
        {
            "customerId": "cust_3333333",
            "depth": 6
        }
    ]
}

Graph Features

You can retrieve features of the graph centred around a target customer either by adding the query parameter features=true to any of the above linking requests, or by sending a separate GET request to /v2/connect/customers/:customerID. The features relate to:

  • The number of hops to a chargeback or reviewed fraudster (-1 is used when there is no chargeback or reviewed fraudster within depth)
  • The number of each node type.
  • The Min, Max and Mean degree (count of connections) of each node type.
  • The stats on the age of network links seen during the BFS search. Ages are in seconds. GrowthRates are edges/hour. ‘Local’ values are calculated to a depth of 2 hops. ‘General’ values are calculated to a depth of 6 hops.
  • The mean degree across all node types we count degree for.
  • The tags found during the network search, and the closest depth at which they were found.

Each feature is calculated within depth hops of the target node. Counting stops when a chargeback or reviewed fraudster is reached.

Here’s what the GET request looks like.

GET /v2/connect/customers/61283761287361?depth=10 HTTP/1.1
Authorization: token ...
Content-Type: application/json

HTTP/1.1 200 OK
Content-Type: application/json
{
    "timestamp": 1532439836,
    "customerID": "61283761287361",
    "count" : 60,
    "customerCount": 5,
    "cardCount": 4,
    "chargebackCount": 1,
    "reviewedFraudsterCount": 1,
    "reviewedGenuineCount": 0,
    "emailCount": 4,
    "phoneCount": 3,
    "deviceCount": 4,
    "hopsToFraud": 3,
    "customerDegreeMin": 2,
    "customerDegreeMean": 3.5,
    "customerDegreeMax": 4,
    "cardDegreeMin": 1,
    "cardDegreeMean": 1.2,
    "cardDegreeMax": 2,
    "emailDegreeMin": 1,
    "emailDegreeMean": 1.3,
    "emailDegreeMax": 3,
    "phoneDegreeMin": 1,
    "phoneDegreeMean": 1.1,
    "phoneDegreeMax": 2,
    "deviceDegreeMin": 1,
    "deviceDegreeMean": 1.472,
    "deviceDegreeMax": 3,
    "edgeGeneralMeanAge": 1800,
    "edgeGeneralGrowthRate": 4,
    "edgeGeneralCount": 5,
    "edgeLocalMeanAge": 720,
    "edgeLocalGrowthRate": 3,
    "meanDegree": 4.7,
    "edgeLocalCount": 1,
    "tags": [
        {
            "tagName": "VIP",
            "depth": 7
        },
        {
            "tagName": "Suspected fraud",
            "depth": 3
        }
    ]
}

Here’s what it looks like if you add features=true to a linking request.

POST https://api.ravelin.com/v2/connect?depth=10&features=true HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
    "customerId": "61283761287361",
    ...
}

HTTP/1.1 200 OK
Content-Type: application/json
{
    "timestamp": 1532439836,
    "customerID": "61283761287361",
    "count" : 60,
    "customerCount": 5,
    "cardCount": 4,
    "chargebackCount": 1,
    "reviewedFraudsterCount": 1,
    "reviewedGenuineCount": 0,
    "emailCount": 4,
    "phoneCount": 3,
    "deviceCount": 4,
    "hopsToFraud": 3,
    "customerDegreeMin": 2,
    "customerDegreeMean": 3.5,
    "customerDegreeMax": 4,
    "cardDegreeMin": 1,
    "cardDegreeMean": 1.2,
    "cardDegreeMax": 2,
    "emailDegreeMin": 1,
    "emailDegreeMean": 1.3,
    "emailDegreeMax": 3,
    "phoneDegreeMin": 1,
    "phoneDegreeMean": 1.1,
    "phoneDegreeMax": 2,
    "deviceDegreeMin": 1,
    "deviceDegreeMean": 1.472,
    "deviceDegreeMax": 3,
    "edgeGeneralMeanAge": 1800,
    "edgeGeneralGrowthRate": 4,
    "edgeGeneralCount": 5,
    "edgeLocalMeanAge": 720,
    "edgeLocalGrowthRate": 3,
    "meanDegree": 4.7,
    "edgeLocalCount": 1,
    "tags": [
        {
            "tagName": "VIP",
            "depth": 7
        },
        {
            "tagName": "Suspected fraud",
            "depth": 3
        }
    ]
}

Graph Feature Limits

Fraud found

If Connect finds fraud (a chargeback or a reviewed fraudster) it will not continue searching any deeper into the network. It will complete looking at nodes at the current depth, then return the results.

Maximum number of visited nodes

Connect will visit at most 5000 nodes searching for fraud. If this limit is reached all the xxxCount fields (customerCount, cardCount…) are set to 5000 in the response to indicate the limit has been hit. Note that count is the sum of the xxxCount fields, so in this case will be set to a multiple of 5000.

Maximum depth

If fraud is not found before the requested maximum depth is reached (specified by the depth parameter in the request), Connect will stop searching and will set the maxDepthReached field to true in the response.

Maximum degree

Connect will not search through nodes connected to over 5000 other nodes. The search will continue, but will ignore this node and its connections. Connect will set the maxDegreeHit field to true in the response to indicate this has happened.

Phone numbers

Connect will not search through phone numbers with more than 500 connections. In this case the autoExcludeHit field will be set to true in the response. In our experience phone numbers with a very large number of connections occur when customers enter invalid but easily guessed phone numbers, such as 123456789.

Genuine reviews

Connect will not search through customers that are marked genuine, except if the customer is the target starting customer.

Sandbox

The graph databases powering Connect will not restore historical data for Sandbox accounts. This may result in some data disappearing from the graph, and inconsistent results when refreshing.

Historical Graph Features

A popular use case for Connect Graph Features is inclusion in use of machine learning systems. Such systems often need large amounts of data to perform well. We can produce a file of historical features that correspond to the response that Connect would have given, had you been using it in the past. These can then be joined onto your historical training data for models to ensure you have coverage throughout history. Please speak to your account manager to arrange this.

Backfill

After your live integration is working and you are using features deterministically, we recommend backfilling historical data into Connect. It is extremely useful as it allows Connect to be seeded with historical connections.

The same API is available under the path /v2/backfill/connect to be used for batch upload of historical data. This API has a higher, separate rate limit to /v2/connect so that you do not interrupt your production system’s use of Connect. The additions are processed asynchronously to the request.

If you cannot reasonably backfill your data to these endpoints, please discuss with your account manager: we can accept data in other formats (CSV, TSV) and process it using our own infrastructure.

Example Request

An example request for the Connect Endpoint with all entities populated is shown below:

POST /v2/connect HTTP/1.1
Authorization: token ...
Content-Type: application/json

{
  "timestamp": 1512828988826,
  "customer": {
    "customerId": "abc-123-ZYZ",
    "registrationTime": 1479302798,
    "familyName": "Smith",
    "givenName": "John",
    "name": "John Smith",
    "email": "jsmith123@example.com",
    "emailVerifiedTime": 1479302798,
    "telephone": "+16045555555",
    "telephoneVerifiedTime": 1479302798,
    "telephoneCountry": "GBR",
    "tags": {
      "foo": true,
      "bar": false
    },
    "country": "GBR",
    "custom": {
      "foo": "bar",
      "biz": "baz",
      "one": 1
    }
  },
  "paymentMethods": [
    {
      "card": {
        "paymentMethodId": "123-abc-XYZ",
        "nickName": "joescard",
        "lastVerified": 1480340580,
        "banned": false,
        "active": true,
        "registrationTime": 1480340580,
        "custom": {
          "foo": "bar",
          "biz": "baz",
          "one": 1
        },
        "instrumentId": "123-abc-XYZ",
        "cardBin": "123456",
        "cardLastFour": "1234",
        "cardType": "visa",
        "expiryMonth": 4,
        "expiryYear": 2020,
        "nameOnCard": "John Smith",
        "successfulRegistration": true,
        "issuer": "barclaycard",
        "countryIssued": "GBR",
        "prepaidCard": false,
        "billingAddress": {
          "latitude": 51.503252,
          "longitude": -0.127899,
          "geohash": "gcpuvp",
          "street1": "123 fake st.",
          "street2": "floor 4, flat 48",
          "neighbourhood": "Hackney",
          "zone": "1",
          "city": "London",
          "region": "California",
          "country": "GBR",
          "poBoxNumber": "1234",
          "postalCode": "E1 1AA",
          "custom": {
            "foo": "bar",
            "biz": "baz",
            "one": 1
          }
        },
        "billingFamilyName": "Smith",
        "billingGivenName": "John",
        "corporateCard": true,
        "virtualCard": true
      }
    }
  ],
  "nationalIdentifications": [
    {
      "driversLicense": {
        "idNumber": "10261985",
        "jurisdictionCountry": "USA",
        "jurisdictionState": "CA",
        "name": "Marty McFly"
      }
    }
  ],
  "vehicles": [
    {
      "plate": "OUTATIME",
      "jurisdictionCountry": "USA",
      "jurisdictionState": "CA",
      "make": "DeLorean Motor Company",
      "model": "DeLorean",
      "year": 1983,
      "vin": "2GTEK13M081122443"
    }
  ],
  "device": {
    "deviceId": "abc-123-ZYZ",
    "type": "phone",
    "manufacturer": "google",
    "model": "Pixel XL",
    "os": "android",
    "browser": "Chrome 42",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
  },
  "chargeback": {
    "chargebackId": "abc-123-XYZ",
    "gateway": "Stripe",
    "gatewayReference": "abc-123-XYZ",
    "reason": "FRAUD",
    "status": "LOST",
    "amount": 15212,
    "currency": "GBP",
    "disputeTime": 1479302798,
    "liabilityShifted": true,
    "nonFraud": false,
    "custom": {
      "foo": "bar",
      "biz": "baz",
      "one": 1
    }
  },
  "review": {
    "label": "FRAUDSTER",
    "comment": "Definitely a fraudster.",
    "reviewer": {
      "name": "tom@mycompany.com",
      "email": "Tom"
    }
  },
  "customNode": {
    "nodeType": "group",
    "nodeId": "group-abc-123-ZYZ",
    "nodeName": "Group abc-123-ZYZ"
  }
}

Feedback

© Ravelin Technology Ltd. All rights reserved