curl --request POST \
--url https://api.platform.sandbox.dakota.xyz/card_dispute_reports \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"description": "Cardholder says they never authorized this charge and still has the card.",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
card_id: '2tQRvvnYkN6edEJUTmF1LzTj2ug',
card_transaction_id: '2ZFHrqBHb3cTfLVkFSGmHZqdDPi',
client_reference: 'SUP-48213',
reason: 'unauthorized',
description: 'Cardholder says they never authorized this charge and still has the card.',
disputed_amount: '39.00',
disputed_currency: 'USD',
consumer_notified_client_at: '2026-09-18T14:02:11Z',
client_forwarded_at: '2026-09-18T16:40:00Z'
})
};
fetch('https://api.platform.sandbox.dakota.xyz/card_dispute_reports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.sandbox.dakota.xyz/card_dispute_reports"
payload = {
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"description": "Cardholder says they never authorized this charge and still has the card.",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.sandbox.dakota.xyz/card_dispute_reports"
payload := strings.NewReader("{\n \"card_id\": \"2tQRvvnYkN6edEJUTmF1LzTj2ug\",\n \"card_transaction_id\": \"2ZFHrqBHb3cTfLVkFSGmHZqdDPi\",\n \"client_reference\": \"SUP-48213\",\n \"reason\": \"unauthorized\",\n \"description\": \"Cardholder says they never authorized this charge and still has the card.\",\n \"disputed_amount\": \"39.00\",\n \"disputed_currency\": \"USD\",\n \"consumer_notified_client_at\": \"2026-09-18T14:02:11Z\",\n \"client_forwarded_at\": \"2026-09-18T16:40:00Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "33Lm2Xc7Vb9Nq4Rt6Yw8Ze1Ua3S",
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z",
"state": "received",
"dakota_filed_with_vendor_at": null,
"vendor_dispute_reference": null,
"rejection_reason": null,
"created_at": 1758220800,
"updated_at": 1758220800
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}Report a card dispute
Record that one of your cardholders told you they dispute a card transaction, and when they told you.
This does not file a dispute with a card network. Nothing in this request reaches a card network, and nothing here changes the card transaction’s status, reverses an authorization, or moves money. A Dakota operator files the dispute separately, by hand, and records the instant they did so. This endpoint captures the report and starts the clock against which that filing is measured.
Send consumer_notified_client_at as the instant the cardholder told
YOU, and client_forwarded_at as the instant you passed it to Dakota.
The two are stored separately and neither is derived from the other,
because the gap between them is yours and the gap after them is
Dakota’s. consumer_notified_client_at must not be later than
client_forwarded_at, and neither may be in the future.
client_reference is your own case identifier. It is unique per
client: resubmitting a reference already on file is answered with 409
naming the report that exists, so a retry after a timeout cannot
produce a second record of one notice.
card_id is required. card_transaction_id is optional — send it when
you know which transaction is disputed, and omit it when you do not.
Omitting it is not a reason to delay: the report is recorded either
way, and the transaction can be attached later.
description is the cardholder’s own account of what happened. It is
stored for the operator who files the dispute and is deliberately
absent from the response: you sent it, and it is not echoed back.
curl --request POST \
--url https://api.platform.sandbox.dakota.xyz/card_dispute_reports \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"description": "Cardholder says they never authorized this charge and still has the card.",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
card_id: '2tQRvvnYkN6edEJUTmF1LzTj2ug',
card_transaction_id: '2ZFHrqBHb3cTfLVkFSGmHZqdDPi',
client_reference: 'SUP-48213',
reason: 'unauthorized',
description: 'Cardholder says they never authorized this charge and still has the card.',
disputed_amount: '39.00',
disputed_currency: 'USD',
consumer_notified_client_at: '2026-09-18T14:02:11Z',
client_forwarded_at: '2026-09-18T16:40:00Z'
})
};
fetch('https://api.platform.sandbox.dakota.xyz/card_dispute_reports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.sandbox.dakota.xyz/card_dispute_reports"
payload = {
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"description": "Cardholder says they never authorized this charge and still has the card.",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.sandbox.dakota.xyz/card_dispute_reports"
payload := strings.NewReader("{\n \"card_id\": \"2tQRvvnYkN6edEJUTmF1LzTj2ug\",\n \"card_transaction_id\": \"2ZFHrqBHb3cTfLVkFSGmHZqdDPi\",\n \"client_reference\": \"SUP-48213\",\n \"reason\": \"unauthorized\",\n \"description\": \"Cardholder says they never authorized this charge and still has the card.\",\n \"disputed_amount\": \"39.00\",\n \"disputed_currency\": \"USD\",\n \"consumer_notified_client_at\": \"2026-09-18T14:02:11Z\",\n \"client_forwarded_at\": \"2026-09-18T16:40:00Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "33Lm2Xc7Vb9Nq4Rt6Yw8Ze1Ua3S",
"card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"client_reference": "SUP-48213",
"reason": "unauthorized",
"disputed_amount": "39.00",
"disputed_currency": "USD",
"consumer_notified_client_at": "2026-09-18T14:02:11Z",
"client_forwarded_at": "2026-09-18T16:40:00Z",
"state": "received",
"dakota_filed_with_vendor_at": null,
"vendor_dispute_reference": null,
"rejection_reason": null,
"created_at": 1758220800,
"updated_at": 1758220800
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}Authorizations
Headers
Unique key to ensure request idempotency. If the same key is used within a certain time window, the original response will be returned instead of executing the request again.
Body
The dispute report.
A report that a cardholder disputes a card transaction.
Recording it does not file a dispute with a card network, does not change the card transaction's status, and does not move money.
KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
Your own case identifier for this report, unique across your reports. Resubmitting one already on file is answered with 409 naming the report that exists, so a retry after a timeout cannot record one notice twice. An idempotency key cannot do this job: it expires, and a client retrying with a fresh key would otherwise file a second report.
1 - 255"SUP-48213"
Why the cardholder disputes the transaction. A closed set, so the
portfolio can be counted by reason. Use other rather than a
reason that is nearly right — a wrong reason is worse than an
unclassified one.
unauthorized, not_received, incorrect_amount, duplicate, cancelled_recurring, other "unauthorized"
When the cardholder told you. Dakota cannot observe this, so you
assert it. Must not be later than client_forwarded_at, and must
not be in the future.
"2026-09-18T14:02:11Z"
When you passed the report to Dakota. Must not be in the future.
"2026-09-18T16:40:00Z"
KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
The cardholder's own account of what happened, for the operator who files the dispute. Deliberately absent from the response: you sent it, and it is not echoed back.
4000"Cardholder says they never authorized this charge and still holds the card."
The disputed amount in MAJOR currency units, as a decimal string.
Omit both this and disputed_currency when the whole transaction
is disputed; send both for a partial dispute.
"42.50"
ISO 4217 currency code for disputed_amount. Required with it, and refused without it.
"USD"
Response
The report was recorded. state is received when a card transaction was named and awaiting_transaction when it was not.
Dakota's record that a cardholder disputed a card transaction, and of what Dakota did about it.
It carries neither description nor the identity of the operator who
filed: the first is the cardholder's own words, which you supplied and
which are not echoed back, and the second is internal.
KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
Your own case identifier, as you sent it.
"SUP-48213"
How far the report has travelled. received is a report Dakota can
act on; awaiting_transaction is one whose card transaction is not
yet known; filed_at_vendor means an operator filed it by hand;
linked means it is tied to the resulting dispute; ambiguous
means several live reports share the disputed transaction and a
person must choose; rejected is how a report ends without a link.
linked and rejected are terminal.
received, awaiting_transaction, filed_at_vendor, linked, ambiguous, rejected "received"
Why the cardholder disputes the transaction, as you sent it.
unauthorized, not_received, incorrect_amount, duplicate, cancelled_recurring, other "unauthorized"
When the cardholder told you, as you asserted it.
"2026-09-18T14:02:11Z"
When you passed the report to Dakota, as you asserted it.
"2026-09-18T16:40:00Z"
Unix timestamp (seconds) when Dakota recorded the report. Server-observed, unlike the two instants you assert.
1758211200
Unix timestamp (seconds) of the last change.
1758297600
The disputed card transaction, once it is known. Null while it is not.
"2B5J8KZ9N7M1K3P6Q8R4T7V9"
The disputed amount in major currency units. Null when the whole transaction is disputed.
"42.50"
ISO 4217 currency code for disputed_amount.
"USD"
When a Dakota operator filed the dispute by hand. Null until that
happens, and write-once thereafter. The gap between
consumer_notified_client_at and this instant is Dakota's own
exposure window.
"2026-09-19T09:15:00Z"
The reference the filing produced, once the report is linked.
"dsp_9f2c41"
Why the report ended without a link. Set only when state is rejected.
"Cardholder withdrew the report."
Was this page helpful?

