Migrate from 2024-03-18 to 2025-04-01
This guide describes every change between API version 2024-03-18 and 2025-04-01 for both the Merchants API and the Platforms API. The deltas below come from comparing the two OpenAPI specs directly, so each item reflects an actual difference in paths, request bodies, response schemas, enums, or required fields.
Version 2025-04-01 introduces breaking changes. Read the sections that apply to your integration before you switch.
This is not a drop-in upgrade
Several endpoints from 2024-03-18 are not present in 2025-04-01, and shared endpoints changed their request and response shapes. Plan to update your code, not just the version string in the URL.
How to set the version
Chargeflow uses date-based versioning in the request path. The version is the date segment after /public/. To move to 2025-04-01, replace the date in every request path.
Authentication did not change. Both versions use the x-api-key request header with the same production server, https://api.chargeflow.io.
curl https://api.chargeflow.io/public/2024-03-18/disputes \
-H "x-api-key: YOUR_API_KEY"For background on how versions work, see API versioning.
Merchants API changes
Endpoint changes
| Method and path | 2024-03-18 | 2025-04-01 | Change |
|---|---|---|---|
GET /disputes | Yes | Yes | Response shape changed, query parameters reduced |
GET /disputes/{disputeId} | No | Yes | New endpoint |
PATCH /disputes/{disputeId} | No | Yes | New endpoint (Enrich Dispute) |
POST /disputes | Yes | No | Removed |
POST /disputes/{disputeId}/order | Yes | Yes | Carried over |
POST /disputes/{disputeId}/evidence | Yes | Yes | Unchanged |
POST /disputes/{disputeId}/subscription | No | Yes | New endpoint |
POST /disputes/{disputeId}/transaction | No | Yes | New endpoint |
POST /disputes/{disputeId}/user_events_log | No | Yes | New endpoint |
GET /alerts | No | Yes | New endpoint |
GET /alerts/{alertId} | No | Yes | New endpoint |
POST /alerts/{alertId}/outcome | No | Yes | New endpoint |
POST /customer-communication | No | Yes | New endpoint |
POST /data-subject/removal | No | Yes | New endpoint |
GET /webhooks | Yes | Yes | Response shape changed |
POST /webhooks | Yes | Yes | Unchanged ({event, url}, one event per registration) |
DELETE /webhooks/{id} | Yes | Yes | Unchanged |
GET /health-check | Yes | Yes | Unchanged |
GET /health-check/access-key | Yes | Yes | Unchanged |
Removed endpoints
These endpoints exist in 2024-03-18 but are not in 2025-04-01. If you call them, you need to stop or move to a replacement.
| Removed endpoint | Notes |
|---|---|
POST /disputes | No direct equivalent in the Merchants API for 2025-04-01. To enrich an existing dispute, use PATCH /disputes/{disputeId} and the per-resource POST endpoints instead. |
GET /disputes response changed
The list response was restructured. The top-level fields and the per-item shape both changed.
| 2024-03-18 | 2025-04-01 |
|---|---|
totalCount (number) | moved under pagination.totalCount (integer) |
hasMore (boolean) | removed |
data (array of objects) | renamed to disputes (array) |
| no pagination object | new pagination object with totalCount, offset, limit, totalPages |
In 2024-03-18, each item in data had a fixed shape with chargeflowDisputeId, a nested dispute object (with processorId, processor, amount, status, reason, responseDueDate), and a nested transaction object. In 2025-04-01, the disputes array items use the flat snake_case dispute shape (id, source, source_id, account_id, created_at, reason, due_by, amount, currency, status, stage, closed_at), with related resources referenced rather than embedded - do not rely on the old data[].dispute and data[].transaction structure. To read a single dispute with full detail, use the new GET /disputes/{disputeId} endpoint.
The query parameters on GET /disputes were also reduced.
| Query parameter | 2024-03-18 | 2025-04-01 |
|---|---|---|
offset | Yes (number) | Yes (integer) |
limit | Yes (number) | Yes (integer) |
dateCreatedFrom | Yes | Removed |
dateCreatedTo | Yes | Removed |
amountFrom | Yes | Removed |
amountTo | Yes | Removed |
statusNames | Yes (enum) | Removed |
reason | Yes (enum) | Removed |
processorNames | Yes (enum) | Removed |
Filtering
If you relied on date, amount, status, reason, or processor filters in the query string, that filtering is no longer available on GET /disputes in 2025-04-01. Plan to filter on your side after fetching, or fetch individual disputes by ID.
GET /webhooks response changed
The webhook list items are simpler in 2025-04-01.
| Field | 2024-03-18 | 2025-04-01 |
|---|---|---|
success | boolean | boolean |
data[].id | string | string |
data[].event | enum (webhook.test, dispute.created, evidence.ready, evidence.error, alerts.created, alerts.updated, alerts.transaction.linked, *) | plain string, no enum |
data[].url | string | string |
data[].active | boolean | removed |
data[].version | string | removed |
Unchanged Merchants endpoints
POST /disputes/{disputeId}/evidence, DELETE /webhooks/{id}, GET /health-check, and GET /health-check/access-key have the same request and response shapes in both versions. The evidence upload still accepts the same two oneOf variants and the same evidenceUploadCategory enums (tracking_information, customer_communication, invoice for the first variant, and additional_evidence, additional_notes for the second).
New Merchants endpoints
2025-04-01 adds several endpoints. The notable request and response details are below.
GET /disputes/{disputeId} returns a single dispute with nested transaction, subscription, and order objects. Note that its reason enum is the smaller set fraud, not_received, not_as_described, canceled_recurring_billing, duplicate_charge, credit_not_processed, other, and status is one of needs_response, under_review, won, lost. It also includes a stage enum (Chargeback, Inquiry, Pre_arbitration, Arbitration) and a source enum listing supported processors.
POST /disputes/{disputeId}/subscription creates subscription context for a dispute. Required fields: source_id, created_at, start_date, frequency (day, week, month, year), and frequency_count.
GET /alerts and GET /alerts/{alertId} return alert records, including a nested network_transaction object and an optional transaction. GET /alerts wraps results in alerts plus the same pagination object used by GET /disputes.
POST /alerts/{alertId}/outcome records an alert outcome. Required field: outcome, one of refunded, previously_refunded, duplicate, decline, error. It returns 202 with no body.
POST /customer-communication submits communication tied to one or more disputes. Required fields: source_id, disputes (array of strings), and messages. Each message requires sender, date, and body_plain_text, and may set a type of email, chat, transcript, form, or sms.
Platforms API changes
The Platforms API changed more than the Merchants API. Every 2024-03-18 Platforms endpoint was removed, and 2025-04-01 introduces a new set of endpoints with a new naming and data model.
Endpoint changes
| Method and path | 2024-03-18 | 2025-04-01 | Change |
|---|---|---|---|
GET /disputes | Yes | No | Removed |
POST /disputes | Yes | No | Removed |
POST /disputes/{disputeId}/order | Yes | No | Removed |
POST /platform/disputes | No | Yes | New endpoint (replaces dispute creation) |
POST /accounts | No | Yes | New endpoint |
GET /accounts/{accountId} | No | Yes | New endpoint |
POST /evidence | No | Yes | New endpoint |
GET /evidence/{evidenceId} | No | Yes | New endpoint |
No shared Platforms endpoints
There are no Platforms endpoints common to both versions. The 2025-04-01 Platforms API is a new surface, so treat the migration as a rewrite of your Platforms integration rather than a field rename.
Removed Platforms endpoints
| Removed endpoint | 2025-04-01 direction |
|---|---|
GET /disputes | No list endpoint in 2025-04-01. Fetch a single record instead, for example via GET /evidence/{evidenceId}. |
POST /disputes | Replaced by POST /platform/disputes with a new request body. |
POST /disputes/{disputeId}/order | Order data is now nested inside the dispute or evidence request body, not a separate call. |
Dispute creation model changed
The old POST /disputes and the new POST /platform/disputes both create a dispute, but the request bodies are different. The data model moved from a flat, processor-oriented payload to a nested model with transaction, subscription, and order objects, and the field names changed from camelCase to snake_case.
Old field (POST /disputes) | New field (POST /platform/disputes) |
|---|---|
disputeId (required) | not used as input; the response returns id |
creationDate (required) | created_at (required) |
due_by (required) | due_by (required) |
disputeAmount (required) | amount (required) |
currency (required) | currency (required) |
processor (required) | not present; use source_id (required) plus the response source enum |
isChargeRefundable (required) | removed |
handleByChargeflow (required) | removed |
reason (required, large enum) | reason (required, smaller enum) |
status (enum needs_response, warning_needs_response) | status (required, enum needs_response, under_review, won, lost) |
no account_id | account_id (required) |
products, pastPayments (flat arrays) | nested under order and transaction objects |
New required fields on POST /platform/disputes: source_id, account_id, created_at, reason, due_by, amount, currency, status.
The reason enum is smaller and uses different values.
Old reason values | New reason values |
|---|---|
general, fraudulent, duplicate, subscription_canceled, product_unacceptable, product_not_received, unrecognized, credit_not_processed, incorrect_account_details, insufficient_funds, bank_cannot_process, debit_not_authorized, goods_services_returned_or_refused, goods_services_cancelled, transaction_amount_differs, retrieved | fraud, not_received, not_as_described, canceled_recurring_billing, duplicate_charge, credit_not_processed, other |
Map your old reason values to the new set before you send them. There is no automatic conversion.
The new request body also supports rich nested objects:
transactionwithpayment_method(includingbrand,wallet, and achecksobject for 3-D Secure and AVS results) andbilling_address.subscriptionwithfrequency,frequency_count,collection_method,pricing_model, andstatus.orderwithcustomer,products(each requiringname,type,quantity,price),shipping_address, andfulfillments.
The response is a full dispute object with id, a source enum, status (needs_response, under_review, won, lost), stage, and the nested transaction, subscription, and order objects.
New Platforms endpoints
POST /accounts creates a platform account. Required fields: owner_name, business_name, business_url, email. The status enum is active or inactive. The response returns the account with a generated id.
GET /accounts/{accountId} returns a single account in the same shape as the create response.
POST /evidence generates evidence. Required fields: account_id and dispute. The dispute field is an anyOf: either { "dispute_id": "..." } to reference an existing dispute, or { "dispute_data": { ... } } to pass the full dispute payload inline. The inline dispute_data uses the same nested transaction, subscription, and order model as POST /platform/disputes. The response returns an evidence record with id, status (in_progress, completed, error), file_url, and file_version.
GET /evidence/{evidenceId} returns an evidence record. Its dispute field is an anyOf of a string ID or the full nested dispute object.
Upgrade checklist
Update the version segment in every request path from /public/2024-03-18/ to /public/2025-04-01/. Keep the x-api-key header as is.
For Merchants GET /disputes, read results from disputes instead of data, and read counts from the new pagination object instead of totalCount and hasMore. Remove any reliance on the old data[].dispute and data[].transaction structure.
Replace removed Merchants query filters (dateCreatedFrom, dateCreatedTo, amountFrom, amountTo, statusNames, reason, processorNames) with client-side filtering or per-dispute lookups via GET /disputes/{disputeId}.
For Merchants GET /webhooks, stop reading data[].active and data[].version, and treat data[].event as a plain string rather than a fixed enum.
Stop calling the removed Merchants endpoint POST /disputes. Adopt the new endpoints (GET /disputes/{disputeId}, PATCH /disputes/{disputeId}, POST /disputes/{disputeId}/subscription, POST /disputes/{disputeId}/transaction, the alerts endpoints, and POST /customer-communication) where they fit your flow.
For Platforms, rebuild your dispute creation against POST /platform/disputes. Rename camelCase fields to snake_case, send the new required fields (source_id, account_id, created_at, reason, due_by, amount, currency, status), and map old reason values to the new seven-value enum.
For Platforms, move order, transaction, and subscription data into the nested objects in the dispute body instead of calling the removed POST /disputes/{disputeId}/order.
Adopt the new Platforms endpoints you need: POST /accounts and GET /accounts/{accountId} for account management, and POST /evidence and GET /evidence/{evidenceId} for evidence generation.
Confirm connectivity and credentials on the new version with GET /health-check and GET /health-check/access-key, which are unchanged.