Enrich a dispute
The PATCH dispute endpoint: upsert semantics, array merge behavior, inline data creation versus linking existing objects, and the response shape.
Enrichment is the process of sending additional evidence and signals to Chargeflow to strengthen a dispute response. Disputes are often vague: they arrive without the full context of a transaction's history and associated entities. By enriching disputes with comprehensive data points, such as order details, user activity logs, customer communications, and fulfillment records, you provide a clearer and more compelling narrative for Chargeflow's AI agents to work with.
Why enrichment matters
- Reduces missing-evidence gaps that weaken the narrative.
- Allows Chargeflow to build a tight, reason-code-specific response.
- Improves automation quality, enabling more effective handling of future disputes.
Tip
Share targeted, high-value artifacts that directly address the issuer's reason code. That is the fastest and easiest way to improve your chance of winning.
If you do not see a guide tailored to your business, contact Chargeflow. A risk and fraud analyst will help you identify which artifacts will move the needle.
General recommendations
Regardless of your business model, the following data points are useful for most dispute reasons:
- Customer identity: Customer name and email add credibility by demonstrating that the business has accurate, comprehensive customer records.
- Addresses: IP address, shipping address, and billing address prove delivery, verify that shipping and billing locations match, and confirm that the IP address aligns with the customer's location.
- Order and product information: Product descriptions, prices, discounts, refund records, and images show that the customer had access to clear and accurate information about their purchase.
Start with a gap analysis
Chargeflow already pulls a lot of dispute data from the tools you connect. Build enrichment for what is missing, not for everything:
- Connect your payment processor and billing platform first in the Chargeflow App. See Integrations.
- Review what Chargeflow pulled. Fetch a few recent disputes with
expandand note which fields are empty. - Build enrichment only for the missing fields, following the enrichment integration guide.
What each source typically provides
Coverage varies by provider and by how your account is configured, so treat this as a starting point and confirm it against your own disputes in step 2.
| Source | Typically provides | Common gaps |
|---|---|---|
| Payment processors (Stripe, PayPal, Adyen, and others) | Dispute reason and amount, transaction, card details and AVS/CVC/3DS checks | Customer IP address, phone, order contents, fulfillment, product usage |
| eCommerce platforms (Shopify, WooCommerce) | Order, products, shipping address, fulfillment and tracking, customer email | Login and usage history, support conversations |
| Subscription and billing platforms | Plan, billing frequency, payment history, cancellation date and reason | Login and usage history, IP address, support conversations |
| Customer communication tools (Gmail, Zendesk, Gorgias) | Support threads with the customer | Everything outside the conversation |
High-value fields to fill first
| Field | Why it matters |
|---|---|
IP address (order.customer.ip_address) | The strongest fraud signal: shows the purchase came from the cardholder's usual location or device. Many processors do not return it. |
Email (order.customer.email) | Ties the purchase to a known customer account and to prior undisputed orders. |
Phone (order.customer.phone_number) | A second identity signal that corroborates the cardholder. |
Billing address (transaction.billing_address) | Matched against the card's AVS result and the shipping address, which is what issuers check first on a fraud dispute. |
These four fields matter most on fraud disputes, where the question is whether the cardholder made the purchase.
The update dispute endpoint
Send all dispute-related evidence to Chargeflow with a single call:
PATCH https://api.chargeflow.io/public/2025-04-01/disputes/{disputeId}Use the Chargeflow dispute ID (dispute.id), available in the dispute.created webhook payload, as the path parameter.
Key ideas
- Upsert semantics: Send only the fields you have. Chargeflow will add new fields or update existing ones. You do not need to resend unchanged data.
- One endpoint for the core payload: Transaction and order data go through this endpoint. Subscription records are a separate call on the same dispute, listed under Disputes:
POST /disputes/{disputeId}/subscription. Communications have their own Customer Communication endpoint. - Override or provide: If Chargeflow has already pulled a signal from a partner provider, you can override it by sending your own value. Chargeflow will adapt the response accordingly.
- Only shared data is used: the dispute response is built from what your connected integrations expose plus what you send here. A field you hold back, or one your integration does not expose, cannot appear in the evidence, so send anything you want argued.
Important: array merge behavior
Warning
When updating array fields (for example, products or fulfillments), the API treats the passed
array as the exact array to be stored.
- To add an item, include the existing items and the new item in the payload.
- If you omit existing items, they will be removed.
Example: appending a product
Current stored value:
"order": {
"products": [
{
"name": "Shoes",
"id": "123456789",
"type": "physical_good",
"quantity": 1,
"description": "Nice shoes",
"price": 150
}
]
}To append a new product, read the current array (or use the dispute.created event payload) and send the full array including the new item:
{
"order": {
"products": [
{
"name": "Shoes",
"id": "123456789",
"type": "physical_good",
"quantity": 1,
"description": "Nice shoes",
"price": 150
},
{
"name": "Socks",
"id": "987654321",
"type": "physical_good",
"quantity": 2,
"description": "Comfort socks",
"price": 20
}
]
}
}Note
If you omit the original Shoes item in the payload above, Chargeflow will replace the stored
array with only Socks. The Shoes item would be removed.
What products represents
order.products[] lists the items the customer purchased in the disputed order: one entry per line item, with the name, description, price, and quantity they paid for. A SaaS plan is a product with type: "digital_good".
Related data that is not a purchased item goes elsewhere:
| Data | Where it belongs |
|---|---|
| Plan, billing frequency, trial, cancellation | The subscription record, via POST /disputes/{disputeId}/subscription |
| Enabled features, product usage, adoption, logins | A file uploaded as additional_evidence. See Upload evidence |
Example: inline data creation
Use inline creation when the relevant object does not yet exist in Chargeflow, when the dispute is urgent and you need to add evidence in a single step, or when your systems cannot return a Chargeflow object ID.
{
"transaction": {
"payment_method": {
"checks": {
"three_d_secure_result": "passed",
"avs_results": "Y",
"address_line1_check": "passed",
"address_zip_check": "passed",
"cvc_check": "passed"
},
"name": "John Doe",
"type": "card",
"last4": "4242",
"expiry_month": "12",
"expiry_year": "2027",
"brand": "visa",
"country": "US"
},
"billing_address": {
"name": "John Doe",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "New York",
"country": "US",
"state": "NY",
"zip_code": "10001",
"phone": "1(123)4567890"
},
"source_id": "trx_1234567890",
"created_at": "2025-01-27T10:00:00Z",
"type": "paid",
"amount": 100,
"currency": "USD"
}
}Tip
Prefer linking existing Chargeflow objects when possible to avoid duplication and keep payloads small. Use inline creation when linking is not possible or would delay your response.
Example: linking existing objects
If the transaction or order is already stored in Chargeflow, pass the object IDs instead of resending the full payload:
{
"transaction": "b6acc3e8408d1d6e78797725",
"order": "e4d0437fb81cb881cc6bc26a"
}Chargeflow will link those objects to the dispute and reuse their data for enrichment and generation.
Multiple disputes on the same transaction
A single transaction can generate more than one dispute. To avoid duplication, Chargeflow will attempt to reuse enrichment data from previous disputes involving the same transaction. If automatic reuse is not possible or you prefer explicit linking, pass existing Chargeflow object IDs in your PATCH payload. This keeps payloads small and ensures consistent data across related disputes.
Response
When your PATCH request succeeds, Chargeflow returns the updated dispute object. The returned dispute includes the enrichment data you just sent (or linked), so you can confirm the update immediately.
Example response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "dis_12345",
"source_id": "proc_67890",
"account_id": "act_112233",
"ext_account_id": "ext_act_445566",
"created_at": "2025-01-27T10:00:00Z",
"reason": "fraud",
"due_by": "2025-02-10T10:00:00Z",
"source": "stripe",
"amount": 150,
"currency": "USD",
"status": "needs_response",
"stage": "Chargeback",
"closed_at": null,
"evidence": {},
"transaction": {
"id": "trx_654321",
"source_id": "550e8400-e29b-41d4-a716-446655440000",
"created_at": "2025-01-26T15:00:00Z",
"type": "paid",
"amount": 150,
"currency": "USD",
"payment_method": {
"name": "John Doe",
"type": "card",
"last4": "4242",
"expiry_month": "12",
"expiry_year": "2027",
"brand": "visa",
"country": "US",
"checks": {
"three_d_secure_result": "passed",
"avs_results": "Y",
"address_line1_check": "passed",
"address_zip_check": "passed",
"cvc_check": "passed"
}
},
"billing_address": {
"name": "John Doe",
"line1": "123 Main Street",
"line2": "Apt 4B",
"city": "New York",
"country": "US",
"state": "NY",
"zip_code": "10001",
"phone": "1(123)4567890"
}
},
"order": {
"id": "ord_98765",
"source_id": "748e2a7c-4d21-11ee-8c99-0242ac120002",
"account_id": "act_112233",
"ext_account_id": "ext_act_445566",
"created_at": "2025-01-26T14:30:00Z",
"payment_status": "paid",
"name": "#ORD-98765",
"type": "pre_order",
"amount": 150,
"currency": "USD",
"customer": {
"name": "John Doe",
"email": "john.doe@example.com",
"customer_since": "2023-06-15T12:00:00Z",
"order_count": 10,
"phone_number": "1(123)4567890",
"ip_address": "192.168.1.1",
"verified_email": true
},
"products": [
{
"name": "Wireless Headphones",
"id": "prod_12345",
"type": "physical_good",
"quantity": 1,
"description": "Noise-canceling wireless headphones with Bluetooth connectivity.",
"image_url": "https://example.com/images/products/12345.jpg",
"price": 150
}
],
"shipping_address": {
"name": "John Doe",
"line1": "123 Main Street",
"line2": "Apt 4B",
"city": "New York",
"country": "US",
"state": "NY",
"zip_code": "10001",
"phone": "1(123)4567890"
},
"fulfillments": [
{
"product_id": "prod_12345",
"shipped_at": "2025-01-26T18:00:00Z",
"shipping_line_title": "FedEx Air Express Shipping",
"shipping_method_price": 0,
"tracking_number": "1Z999AA10123456789",
"courier": "FedEx"
}
]
},
"activity_logs": null,
"customerCommunication": "ccm_01j92p1x8a6y7t4gz8d9w3n5qk",
"booking": null
}Next steps
- Map your internal data schema to Chargeflow fields. Decide which objects you will link by ID versus send inline.
- Subscribe to
dispute.createdso your enrichment flows trigger automatically when a new dispute is ingested. - Pick what you want to add to the dispute: