Skip to main content

Disputes and Chargebacks

Overview

This guide covers the dispute and chargeback process and how to simulate it in the Test environment using the Highnote API.

Account holders can submit disputes when they believe they didn't receive the goods and services they paid for, or when there was unauthorized activity on their financial account. If they win the dispute case and the disputed transaction is reversed, a chargeback is issued.

Card networks have strict rules and timelines for responding to and investigating disputes. Highnote's in-house Disputes Intake Team helps subscribers with the following dispute and chargeback-related processes:

  • Handling dispute intakes from account holders
  • Managing dispute-related documentation requests and receivables for account holders
  • Investigating dispute claims
  • Filing chargebacks for disputed transactions
  • Providing direct support to account holders on the status of disputes and chargebacks
  • Issuing and settling provisional credits
  • Monitoring and maintaining regulatory requirements and timelines

Provisional credits

Provisional credits are issued to an account holder during a dispute case investigation. Depending on your card product type, provisional credits may or may not be required:

  • Consumer card products: Required by Regulation E
  • Commercial card products: Optional

Provisional credits are issued from your product funding account to an account holder's financial account using an internal Highnote transfer. Internal transfers must be done using the Highnote API. See Transfer between Financial Accounts.

Dispute categories

Disputes fall into different categories, which must be noted when submitting a dispute case.

Dispute Case CategoryDescriptionExample
AUTHORIZATIONCard program attempted to collect funds spent by the account holderA clearing transaction without an authorization event
FRAUDAccount holder claims a transaction is fraudulentAn account holder’s payment card is compromised and used for fraudulent purchases
CUSTOMER_DISPUTEAccount holder claims they did not receive paid-for goods and servicesAn account holder purchased a product from an online merchant and never received it
PROCESSING_ERRORTransaction data is incorrectA duplicate charge on an account holder’s financial account

Account holder submitted dispute cases

Live environment

In the Live environment, dispute cases are initiated by the account holder or Highnote, and all are processed by Highnote's Disputes Intake Team (not the Highnote API).

To ensure your account holders can submit dispute cases, provide the following options:

  • Have your account holder call Highnote directly using an Interactive Voice Response (IVR) system.
  • Set up email forwarding to Highnote's Disputes Intake team.

When an account holder submits a dispute, the following information must be collected:

  • Dispute category
  • Account holder's full name (must match the full name on their payment card)
  • The last four digits of the payment card used
  • Transaction ID
  • Transaction posted date
  • Posted transaction amount
  • Disputed amount
  • Merchant ID
  • Summary of dispute reason and any supporting documents

Simulate a dispute case

Test environment only

In the Test environment, you can create dispute cases and simulate the full dispute and chargeback lifecycle with the API.

test with dummy data

Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data.

Simulating disputes and chargebacks triggers financial account activity related to provisional, dispute, or chargeback credits and the associated notification events for case creation and resolution.

When creating a dispute case in the Test environment, you must include the following:

  • Dispute category: See Dispute categories.
  • Dispute eligibility: The disputed transaction must be cleared and disputed within 180 days of the clearing event.
  • If multiple transactions are disputed: A separate dispute case must be submitted for each transaction.
  • If a dispute is unrelated to fraud: The account holder should contact the merchant to resolve it before submitting it to Highnote.
  • If a dispute is related to fraud: You must close any compromised payment cards associated with the account holder's financial account.

Use the following mutation to simulate the creation of a dispute case in the Test environment:

simulateInitiateCardTransactionDispute
Query
mutation simulateInitiateCardTransactionDispute(
$input: SimulateInitiateCardTransactionDisputeInput!
) {
simulateInitiateCardTransactionDispute(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
category
amount {
currencyCode
value
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "cardTransactionEventId": "TRANSACTION_EVENT_ID",
    "category": "FRAUD",
    "amount": {
      "currencyCode": "USD",
      "value": "2000"
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"simulateInitiateCardTransactionDispute": {
"__typename": "PaymentCardTransactionDispute",
"id": "csmdi_22b0b5ded7d8d94207b4e78da5543f3d1b",
"status": "INITIATED",
"category": "FRAUD",
"amount": {
"currencyCode": "USD",
"value": 2000
},
"fromDate": "2024-02-07T17:46:17.713Z",
"throughDate": null
}
},
"extensions": {
"requestId": "REQUEST_ID",
"rateLimit": {
"cost": 13,
"limit": 60060,
"remaining": 60046
}
}
}

Open a chargeback case

Chargeback cases are linked to the parent dispute case and are created if a dispute qualifies for filing with the card network.

If the disputed transaction is below the card product's minimum chargeback amount (set at $25 in the Test environment), a chargeback case id not initiated. Instead, a dispute credit is issued to the financial account.

To simulate a chargeback, use the following mutation with disputeId and amount as input variables:

simulateInitiateCardTransactionChargeback
Query
mutation simulateInitiateCardTransactionChargeback(
$input: SimulateInitiateCardTransactionChargebackInput!
) {
simulateInitiateCardTransactionChargeback(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
chargebacks {
id
requestedAmount {
currencyCode
value
}
receivedAmount {
currencyCode
value
}
status
fromDate
throughDate
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "disputeId": "DISPUTE_ID",
    "amount": {
      "currencyCode": "USD",
      "value": "3500"
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"simulateInitiateCardTransactionChargeback": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "IN_PROGRESS",
"chargebacks": [
{
"id": "CHARGEBACK_ID",
"requestedAmount": {
"currencyCode": "USD",
"value": 3500
},
"receivedAmount": null,
"status": "SUBMITTED",
"fromDate": "2023-10-18T20:10:08.544Z",
"throughDate": null
}
],
"fromDate": "2023-10-18T20:09:53.397Z",
"throughDate": null
}
}
}

Issue provisional credits

For disputed transactions, provisional credits may be issued to a financial account during the investigation. In the Test environment, all consumer card products can issue these credits after a chargeback case has been created.

For credit card products, disputed transactions are removed from the account's balance due, but the available credit may not be released until the dispute is resolved in the account holder's favor.

If the chargeback case is won, the provisional credit remains. If lost, the provisional credit is revoked.

Use the following mutation to simulate issuing a provisional credit for a dispute case:

simulateIssueProvisionalCreditForCardTransactionDispute
Query
mutation simulateIssueProvisionalCreditForCardTransactionDispute(
$input: SimulateIssueProvisionalCreditForCardTransactionDisputeInput!
) {
simulateIssueProvisionalCreditForCardTransactionDispute(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
chargebacks {
id
creditStatus
requestedAmount {
currencyCode
value
}
receivedAmount {
currencyCode
value
}
status
fromDate
throughDate
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "id": "DISPUTE_CASE_ID",
    "chargebackId": "CHARGEBACK_ID"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"simulateIssueProvisionalCreditForCardTransactionDispute": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "IN_PROGRESS",
"chargebacks": [
{
"id": "CHARGEBACK_ID",
"requestedAmount": {
"currencyCode": "USD",
"value": 3500
},
"receivedAmount": null,
"status": "SUBMITTED",
"creditStatus": "PROVISIONAL_CREDIT_PENDING_ISSUED",
"fromDate": "2023-10-18T20:07:51.969Z",
"throughDate": null
}
],
"fromDate": "2023-10-18T20:07:44.301Z",
"throughDate": null
}
}
}

Issue dispute credits

If the disputed amount is below the card product's minimum chargeback threshold, a dispute credit can be issued instead of a provisional credit. The minimum chargeback amount varies by card product and is listed in the feature settings. If the disputed amount qualifies for a chargeback, a dispute credit cannot be issued. In the Test environment, the disputed amount must be less than $25 to issue a dispute credit.

You can optionally indicate the liability of the dispute expense: ISSUER_LIABLE or MERCHANT_LIABLE:

  • If ISSUER_LIABLE is selected, a dispute expense is recorded on the product funding account.
  • If MERCHANT_LIABLE is selected, it is assumed that the dispute was paid for by the network and no expense is recorded.
  • If no liability input is provided, liability is assumed to be on the issuer.

Use the following mutation to simulate issuing a dispute credit:

simulateIssueCreditForCardTransactionDispute
Query
mutation simulateIssueCreditForCardTransactionDispute(
$input: SimulateIssueCreditForCardTransactionDisputeInput!
) {
simulateIssueCreditForCardTransactionDispute(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
category
amount {
currencyCode
value
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "id": "DISPUTE_ID"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"issueCreditForCardTransactionDispute": {
"__typename": "PaymentCardTransactionDispute",
"id": "csmdi_22d3103befd467417e8f330e62cc8f6cd3",
"status": "IN_PROGRESS",
"category": "FRAUD",
"amount": {
"currencyCode": "USD",
"value": 2000
},
"provisionalCreditHistory": null,
"disputeCreditHistory": [
{
"__typename": "PaymentCardTransactionDisputeCredit",
"creditStatus": "CREDIT_ISSUED",
"requestedAmount": {
"currencyCode": "USD",
"value": 2000
},
"receivedAmount": {
"currencyCode": "USD",
"value": 2000
},
"creditIssueFromDate": "2024-07-25T20:38:20.064Z"
}
],
"liablity": "ISSUER_LIABLE",
"fromDate": "2024-07-25T20:38:20.064Z",
"throughDate": null
}
},
"extensions": {
"requestId": "a1937cc0-905d-980f-a12f-be240f68dfb5",
"rateLimit": {
"cost": 11,
"limit": 60060,
"remaining": 60047
}
}
}

Update a dispute case

info

Updating dispute case elements does not impact an associated chargeback case.

You can update the dispute case status to trigger additional notification events such as REJECTED and CANCELLED.

Use the following mutation to simulate updating a dispute case, providing the desired status as an input variable:

simulateUpdateCardTransactionDispute
Query
mutation simulateUpdateCardTransactionDispute(
$input: SimulateUpdateCardTransactionDisputeInput!
) {
simulateUpdateCardTransactionDispute(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
category
amount {
currencyCode
value
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "status": "CANCELLED"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"simulateUpdateCardTransactionDispute": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "CANCELLED",
"category": "FRAUD",
"amount": {
"currencyCode": "USD",
"value": 3500
},
"fromDate": "2023-10-18T19:09:42.589Z",
"throughDate": null
}
}
}

Resolve a chargeback case

Resolving a chargeback case automatically resolves the associated dispute case. The dispute case status update also affects any provisional credits issued. The outcome determines ledger entries and money movement. If no provisional credit was issued for a commercial card, a credit is issued to the financial account when the chargeback is resolved.

To simulate resolving a chargeback case, use the following mutation:

simulateResolvePaymentCardTransactionChargeback
Query
mutation simulateResolvePaymentCardTransactionChargeback(
$input: SimulateResolvePaymentCardTransactionChargebackInput!
) {
simulateResolvePaymentCardTransactionChargeback(input: $input) {
__typename
... on PaymentCardTransactionDispute {
id
status
chargebacks {
id
requestedAmount {
currencyCode
value
}
receivedAmount {
currencyCode
value
}
status
fromDate
throughDate
}
fromDate
throughDate
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{
  "input": {
    "disputeId": "DISPUTE_CASE_ID",
    "id": "CHARGEBACK_ID",
    "receivedAmount": {
      "value": 3500,
      "currencyCode": "USD"
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"simulateResolvePaymentCardTransactionChargeback": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "WON",
"chargebacks": [
{
"id": "CHARGEBACK_ID",
"requestedAmount": {
"currencyCode": "USD",
"value": 3500
},
"receivedAmount": {
"currencyCode": "USD",
"value": 3500
},
"status": "RESOLVED",
"fromDate": "2023-10-18T19:10:13.120Z",
"throughDate": null
}
],
"fromDate": "2023-10-18T19:09:42.589Z",
"throughDate": null
}
}
}

Find dispute cases

You can find dispute cases by querying the following objects:

  • A financial account
  • The transaction event associated with the dispute case
  • Card product

via financial account

You can search for dispute cases and their associated transactions on a financial account using the following query:

getDisputeForFinancialAccount
Query
query getDisputeForFinancialAccount($id: ID!) {
node(id: $id) {
__typename
... on FinancialAccount {
id
paymentCardTransactionDisputes {
... on PaymentCardTransactionDisputeConnection {
edges {
node {
id
amount {
value
currencyCode
}
category
status
chargebacks {
id
requestedAmount {
value
}
receivedAmount {
value
}
creditStatus
status
}
fromDate
throughDate
}
}
}
}
}
}
}
Variables
{
"input": {
"id": "FINANCIAL_ACCOUNT_ID"
}
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"cardTransactionDisputesForFinancialAccount": {
"__typename": "PaymentCardTransactionDisputeConnection",
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"startCursor": "start-cursor",
"endCursor": "end-cursor"
},
"edges": [
{
"cursor": "some-cursor",
"node": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "INITIATED",
"category": "FRAUD",
"amount": {
"currencyCode": "USD",
"value": 100
},
"chargebacks": [],
"fromDate": "2023-03-17T22:39:18.060Z",
"throughDate": "2023-03-17T22:39:18.060Z"
}
}
]
}
}
}

via transaction event

You can find a related dispute case from the associated AUTHANDCLEAR or CLEAR transaction event using the following query:

getClearingDispute
Query
query getClearingDispute($id: ID!) {
node(id: $id) {
__typename
... on TransactionEvent {
id
transaction {
__typename
}
createdAt
... on ClearingEvent {
disputes {
__typename
id
... on PaymentCardTransactionDispute {
amount {
value
currencyCode
}
category
status
chargebacks {
id
requestedAmount {
value
}
receivedAmount {
value
}
creditStatus
status
}
fromDate
throughDate
}
}
}
}
}
}
Variables
{
"input": {
"id": "TRANSACTION_EVENT_ID"
}
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"node": {
"__typename": "ClearingEvent",
"id": "TRANSACTION_EVENT_ID",
"transaction": {
"__typename": "DebitTransaction"
},
"approvedAmount": {
"value": 1500
},
"createdAt": "2023-05-18T20:47:46.787Z",
"disputes": [
{
"id": "DISPUTE_CASE_ID",
"amount": {
"value": 1500,
"currencyCode": "USD"
},
"category": "FRAUD",
"status": "WON",
"chargebacks": [
{
"id": "CHARGEBACK_ID",
"requestedAmount": {
"value": 1500
},
"receivedAmount": {
"value": 1500
},
"creditStatus": "CREDIT_WON",
"status": "WON"
}
],
"fromDate": "2023-05-18T20:42:29.939Z",
"throughDate": null
}
]
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}

via card product

You can also view a paginated list of dispute cases associated with a card product with the following query:

getProduct
Query
query getProduct($id: ID!) {
node(id: $id) {
... on CardProduct {
__typename
id
name
paymentCardTransactionDisputes {
__typename
... on PaymentCardTransactionDisputeConnection {
__typename
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
node {
__typename
id
... on PaymentCardTransactionDispute {
status
category
amount {
value
currencyCode
}
}
}
}
}
}

features {
__typename
enabled
... on DisputeChargebackCardProductFeature {
__typename
chargebackMinimumThreshold {
__typename
value
currencyCode
}
chargebackProvisionalCreditEnabled
disputeMaximumDaySinceTransaction
}
}
}
}
}
Variables
{
"input": {
"id": "CARD_PRODUCT_ID"
}
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"node": {
"__typename": "CardProduct",
"id": "CARD_PRODUCT_ID",
"name": "A Consumer Prepaid",
"paymentCardTransactionDisputes": {
"__typename": "PaymentCardTransactionDisputeConnection",
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false
},
"edges": [
{
"node": {
"__typename": "PaymentCardTransactionDispute",
"id": "DISPUTE_CASE_ID",
"status": "RESOLVED",
"category": "FRAUD",
"amount": {
"value": 1500,
"currencyCode": "USD"
}
}
}
]
},
"features": [
{
"__typename": "DisputeChargebackCardProductFeature",
"enabled": true,
"chargebackMinimumThreshold": {
"__typename": "Amount",
"value": 2500,
"currencyCode": "USD"
},
"chargebackProvisionalCreditEnabled": true,
"disputeMaximumDaySinceTransaction": 180
},
{
"__typename": "AuthorizedUserCardProductFeature",
"enabled": false
}
]
}
},
"extensions": {
"requestId": "REQUEST_ID",
"rateLimit": {
"cost": 25,
"limit": 100,
"remaining": 75
}
}
}