Refund abuse occurs when a customer uses your returns policy so much that it becomes unprofitable.
One of the most common types of refund fraud is when a customer receives an order, but claims it was never delivered and requests a refund. Determined refund fraudsters can even make a business out of exploiting returns policies.
Ravelin can identify behaviour that looks like refund abuse and provide recommendations on whether you should issue refunds.
If you want a recommendation on whether to issue a refund, send the details of the refund to the
Refund API Endpoint,
with the query parameter score=refundRequest
added to the URL.
For example, the URL should be: https://api.ravelin.com/v2/refund?score=refundRequest
refund.status
must be set to OPEN
If the refund is for specific items, send these in the refund.items
array. refundReason
must be provided for each item.
If the refund is not for specific items, set the refund.refundReason
value instead.
We strongly recommend sending all fields marked as important, however the more fields you can populate the better our recommendation.
An example request showing all the refund
fields we recommend is shown below:
{
"timestamp": 1512828988826,
"customer": {
"customerId":"abc-123-ZYZ"
},
"order": {
"orderId": "abcde12345-ZXY"
},
"refund":{
"refundId": "abc-123-GDFS",
"refundRequestTime": 1636629706000,
"status": "OPEN",
"initiatedBy": "CUSTOMER",
"type": "REFUND",
"claim": "FULL",
"policy": "TERMS_AND_CONDITIONS",
"amount": 1000,
"currency": "GBP",
"nonRefundableAmount": 250,
"issuedTo": "ORIGINAL_PAYMENT_METHOD",
"items": [
{
"name": "Midi Dress",
"quantity": 1,
"price": 1000,
"currency": "GBP",
"sku": "1234AAB",
"category": "Clothing",
"subcategory": "Dresses",
"brand": "Trendy Threads",
"refundReason": "ITEM_NOT_RECEIVED"
}
]
},
"device": {
"deviceId": "df020f51-5ebb-4901-82cf-96299225754b"
}
}
The data.action
field in the response will contain Ravelin’s recommendation.
You should either allow or prevent the refund depending on the data.action
value.
The possible values are:
ALLOW
- Issue the refund to the customerPREVENT
- Do not issue the refund to the customerIt is also possible to configure additional action
values, such as MANUAL_REVIEW
,
which can be used to mark suspicious customers for investigation by your fraud team.
We will work with you directly if there are additional action
values you want to implement.
The data.source
field in the response will tell you what generated the refund recommendation.
This can be used for further investigation and analysis.
An example response is shown below.
{
"status": 200,
"timestamp": 1637933719,
"data": {
"customerId": "abc-123-ZYZ",
"action": "PREVENT",
"source": "RULE",
"rules": {
"triggered": [
{
"triggered": true,
"description": "Customer is a serial complainer",
"state": "active",
"action": "PREVENT"
}
]
}
}
}
You should send us the details and outcome of all refund requests, regardless of whether you requested a refund recommendation.
This allows us to learn the behaviour of your customers and make better refund recommendations.
Send the refund details to the Refund API Endpoint.
Do not add the score=refundRequest
query parameter.
An example request is shown below.
{
"timestamp": 1512828988826,
"customer": {
"customerId":"abc-123-ZYZ"
},
"order": {
"orderId": "abcde12345-ZXY",
"status": {
"stage": "refunded"
}
},
"refund": {
"refundId": "abc-123-GDFS",
"refundRequestTime": 1636629706000,
"refundIssuedTime": 1636629706000,
"status": "COMPLETED",
"initiatedBy": "CUSTOMER",
"type": "REFUND",
"claim": "FULL",
"policy": "TERMS_AND_CONDITIONS",
"amount": 7000,
"currency": "GBP",
"issuedTo": "ORIGINAL_PAYMENT_METHOD",
"items": [
{
"name": "Heart Gold Necklace",
"quantity": 1,
"price": 7000,
"currency": "GBP",
"sku": "345682KGP",
"category": "Accessories",
"subcategory": "Jewellery",
"brand": "Trendy Threads",
"refundReason": "CUSTOMER_INCORRECT_ITEM"
}]
},
"transactions":[{
"transactionId": "pi_3Jd",
"paymentMethodId": "card_1Ijim5Bvd0CnXcVWpZz66Idb",
"gateway": "stripe",
"gatewayReference": "65645tfghdhgd",
"amount": 7000,
"currency": "GBP",
"type": "refund",
"success": true
}]
}
If you previously requested a refund recommendation you do not need to send all the details of the refund again.
You can just send refund.refundId
and the fields describing the outcome of the refund request.
If you issued the refund, set the following fields:
refund.status: "COMPLETED"
refund.refundIssuedTime
order.status.stage: refunded
transaction.type: refund
An example request for an issued refund is shown below.
{
"timestamp": 1512828988826,
"customer": {
"customerId":"abc-123-ZYZ"
},
"order": {
"orderId": "abcde12345-ZXY",
"status": {
"stage": "refunded"
}
},
"refund": {
"refundId": "abc-123-GDFS",
"refundIssuedTime": 1512828988826,
"status": "COMPLETED"
},
"transactions":[{
"transactionId": "pi_3Jd",
"paymentMethodId": "card_1Ijim5Bvd0CnXcVWpZz66Idb",
"gateway": "stripe",
"gatewayReference": "65645tfghdhgd",
"amount": 700,
"currency": "GBP",
"type": "refund",
"success": true
}]
}
If you did not issue the refund, set the following fields:
refund.status: "DECLINED"
refund.declineReason
An example request for a declined refund is shown below.
{
"timestamp": 1512828988826,
"customer": {
"customerId":"abc-123-ZYZ"
},
"order": {
"orderId": "abcde12345-ZXY"
},
"refund": {
"refundId": "abc-123-ZYZ",
"status": "DECLINED",
"declineReason": "RAVELIN"
}
}
After completing integration you should test that you correctly handle our refund recommendation responses.
To help with this we support special email addresses which will return a specific refund recommendation response.
These special email addresses only work when using the API key for your sandbox account.
The special email addresses which will force specific refund recommendation responses are shown below:
Customer Email | Action Response |
---|---|
qa-force-refund-allow@ravelin.com |
ALLOW |
qa-force-refund-prevent@ravelin.com |
PREVENT |
qa-force-refund-manualreview@ravelin.com |
MANUAL_REVIEW |
qa-force-refund-review@ravelin.com |
REVIEW |
These email addresses should be used in the customer.email
field.
An example request which will force an ALLOW
action to be returned is shown below:
{
"timestamp": 1512828988826,
"customer": {
"customerId":"abc-123-ZYZ",
"email":"qa-force-refund-allow@ravelin.com"
},
"order": {
"orderId": "abcde12345-ZXY"
},
"refund":{
"refundId": "abc-123-GDFS",
"refundRequestTime": 1636629706000,
"status": "OPEN",
"initiatedBy": "CUSTOMER",
"type": "REFUND",
"claim": "FULL",
"policy": "TERMS_AND_CONDITIONS",
"amount": 1000,
"currency": "GBP",
"nonRefundableAmount": 250,
"issuedTo": "ORIGINAL_PAYMENT_METHOD",
"items": [
{
"name": "Midi Dress",
"quantity": 1,
"price": 1000,
"currency": "GBP",
"sku": "1234AAB",
"category": "Clothing",
"subcategory": "Dresses",
"brand": "Trendy Threads",
"refundReason": "ITEM_NOT_RECEIVED"
}
]
},
"device": {
"deviceId": "df020f51-5ebb-4901-82cf-96299225754b"
}
}
An example testing response containing ALLOW
in the data.action
field is shown below:
{
"status": 200,
"timestamp": 1637933719,
"data": {
"customerId": "abc-123-ZYZ",
"action": "ALLOW",
"source": "RULE"
}
}