> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dakota.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Report a card dispute, and optionally file it

> Record that one of your cardholders told you they dispute a card
transaction, and when they told you.

**Whether this files a dispute depends on `filing_reason`.**

- **Send `filing_reason`** and Dakota files the dispute during this
  request, before you get a response. Filing is not reversible through
  this API. You must also send `card_transaction_ids` naming every
  transaction the dispute covers — except for `atm_deposit_missing`,
  the one account-level reason, which requires an empty list.
- **Omit `filing_reason`** and the report is only recorded. Nothing
  reaches a card network. This is the right call when you cannot yet
  identify the disputed transaction, because a dispute cannot be filed
  without naming one.

Read `filing_state` on the response to learn which happened. `pending`
means the dispute was filed and is awaiting the information the network
requires. `not_filed` means it was not — either because you sent no
`filing_reason`, or because the filing failed. **A `not_filed` report
that carries a `filing_reason` needs following up with Dakota:** the
report is on file and its response clock is running, and because
`client_reference` is unique you cannot resubmit it.

In neither case does this endpoint change the card transaction's
status, reverse an authorization, or move money.

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.


> [!WARNING]
>
> **Sandbox only.** This endpoint is available in sandbox only while we finish development. It is not available in production yet, and its request and response shapes may change before release.


## OpenAPI

````yaml /openapi.yaml post /card_dispute_reports
openapi: 3.0.3
info:
  title: Dakota Platform API
  version: 1.0.0
  description: >-
    Combined API specification for Dakota Platform services:

    - Issuance API: Asset minting and burning operations

    - Onboarding API: Know Your Business/Customer verification

    - On/Off Ramp API: Managing on-ramp and off-ramp accounts

    - Recipients API: Managing destinations for KYB'd entities

    - Transactions API: Viewing transaction history across platform operations


    ## Authentication and API Headers


    All API endpoints require the following headers:


    - `X-Idempotency-Key`: Required for all POST endpoints to ensure request
    idempotency

    - `x-api-key`: Required for authentication across all endpoints


    Note: On /applications endpoints you need a token for authentication instead
    of a x-api-key

    - `x-application-token`: Required for authentication on public /applications
    endpoints (alternative to `x-api-key` where documented)



    ## Rate Limits


    Requests are rate limited per API key. Every response includes the following
    headers:


    | Header | Description |

    | --- | --- |

    | `X-RateLimit-Limit` | Maximum requests allowed in the current one-minute
    window. |

    | `X-RateLimit-Remaining` | Requests remaining in the current window. |

    | `X-RateLimit-Reset` | Absolute Unix timestamp (seconds since epoch) when
    the current rate-limit window resets. |


    When a request is throttled (`429`), responses also include `Retry-After`
    with seconds to wait before retrying.
servers:
  - url: https://api.platform.dakota.xyz
    description: Production environment
  - url: https://api.platform.sandbox.dakota.xyz
    description: Sandbox — safe for testing with simulated data
security:
  - ApiKeyAuth: []
tags:
  - name: Agentic Payments
    x-beta: true
    description: >-
      Beta — agent-driven payments: provision agents, draft and approve spending
      mandates, accept reviewed instructions, and manage scheduled payments.


      **Prerequisites:** Customer onboarded; signer groups attached for
      recognition.

      **Related:** Wallets, Signer Groups, Transactions
  - name: Mandates
    x-beta: true
    description: >-
      Beta — spending mandates: signed, signer-bound authorizations governing
      what may be spent, approved or cancelled by a second recognized signer (§8
      — the dual-control rule that every mandate mutation must be signed by a
      recognized signer OTHER than the bound one). Independent of agents and
      scheduled payments.


      **Prerequisites:** Signer groups attached for recognition.

      **Related:** Signer Groups, Transactions
  - name: Insights
    x-beta: true
    description: >-
      Beta — read-only insight: a deterministic report over a customer's agentic
      activity (funding balances, upcoming obligations, failures, mandate
      headroom and expiry), or — via `GET /insights` — over the whole client's
      book, with portfolio KPIs, daily series and a per-customer roll-up. Never
      moves money, never creates or changes anything.


      **Prerequisites:** Customer onboarded; insight is computed from the
      customer's scheduled payments, mandates, and wallets.

      **Related:** Agentic Payments, Mandates
  - name: Customers
    description: >-
      Manage customer entities representing businesses and organizations
      onboarded to Dakota.


      **Prerequisites:** Complete KYB via Onboarding endpoints before initiating
      money movement.

      **Related:** Onboarding, Recipients, Transactions, Accounts, Wallets
  - name: Wallets
    description: >-
      Manage wallets, balances, and wallet-to-signer-group relationships for
      custody and movement controls.


      **Prerequisites:** Customer must exist. Configure signer groups before
      policy-enforced workflows.

      **Related:** Signer Groups, Policies, Transactions, Customers
  - name: Transactions
    description: >-
      Create, cancel, and retrieve transaction records across account and wallet
      flows.


      **Prerequisites:** Accounts or destinations must be configured based on
      flow type.

      **Related:** Accounts, Recipients, Policies, Events
  - name: Recipients
    description: >-
      Manage recipient entities and destination rails used by customers for
      payouts and transfers.


      **Prerequisites:** Customer must be onboarded and active.

      **Related:** Customers, Transactions, Accounts, Onboarding
  - name: Cards
    description: >-
      Issue and manage cardholders and cards, and follow card transactions.
      Every change is also delivered as a webhook event.


      **Prerequisites:** Customer must be onboarded and the cards capability
      must be available.

      **Related:** Customers, Wallets, Events


      ### Webhook event catalog (v1)


      Every card-family event a client can subscribe to, in one place:


      | Event | Fires when |

      | -- | -- |

      | `cardholder.created` | A cardholder is created. |

      | `cardholder.updated` | Any cardholder change, including every
      review-status transition and deletion (`status: closed`). |

      | `cardholder.information_requested` | A reviewer asks for more
      information; the payload lists the open requirements. |

      | `card.created` | A card is created. |

      | `card.updated` | Any card change: status, spend limit, last4, freeze
      sources. A close arrives here with `status: closed`. |

      | `card_transaction.created` | The first event for a transaction, normally
      an authorization (`status: authorized`) placing a hold. A declined
      authorization also arrives here, with `status: declined`. |

      | `card_transaction.updated` | Every later change to the same transaction
      (see below). |

      | `wallet.card_enablement.completed` | A wallet's card-settlement
      enablement became active. |


      **Card event ordering.** `card.created` and `card.updated` carry the card
      as it stands after

      the change, including `version` and `freeze_sources` (always an array,
      empty when nothing

      holds the card). `version` is strictly increasing per card and matches the
      `version` on the

      card resource. Deliveries can arrive out of order, so keep the highest
      `version` you have

      applied for each card and drop any event whose `version` is not greater
      than it.


      **One transaction stream.** Holds, releases, partial clearings,
      settlement, returns,

      disputes and force posts are not separate event types. They are `status`
      transitions on

      the transaction, delivered as `card_transaction.updated` with the same
      payload shape as

      `card_transaction.created`:


      | What happened | `status` on the event |

      | -- | -- |

      | Transaction known before its first authorization event | `pending` (on
      `card_transaction.created`) |

      | Hold placed (authorization) | `authorized` (on
      `card_transaction.created`, or `card_transaction.updated` after a
      `pending` start) |

      | Hold released without clearing (merchant, issuer or network reversal) |
      `auth_reversed` |

      | Hold expired unused | `expired` |

      | Part of the hold settled | `partially_cleared` (with the new
      `cleared_amount`) |

      | Fully settled | `cleared` |

      | Settled with no prior hold | `force_posted` |

      | Merchant refund | `returned`, usually on a new card transaction for the
      refund while the original purchase stays `cleared`. A refund can also land
      on the purchase's own transaction, which keeps its purchase status until
      the refunds cover everything that cleared and nothing authorized is left
      to clear. A transaction carries a refund whenever `refund_state` has a
      value, whatever its `status`. `returned_amount` is how much was refunded.
      The network returned the money; read `refund_state` for whether it reached
      the customer's wallet: `pending` while owed, then `paid`; `reversed` when
      every refund was cancelled before payout; `failed` when a payout failed.
      `returned` alone is not proof of payout. |

      | Merchant refund on its own transaction, fully reversed before it is paid
      out | `auth_reversed` on the refund's card transaction, with
      `refund_state: reversed`. The refund is withdrawn; `refund_state` is what
      tells it from a released hold. |

      | Chargeback opened | `disputed` (reserved; not emitted yet) |

      | Authorization refused | `declined` (on `card_transaction.created`, or
      `card_transaction.updated` when the transaction already exists). Moves no
      money; read `decline_reason` and `decline_code` for why. |


      `outstanding_amount` is the part of `cleared_amount` that no authorization
      covered, less any refunds: non-zero after a force post or an over-capture.


      **Naming.** A dotted segment names a sub-resource of the resource before
      it, so

      `wallet.card_enablement.*` is a wallet's card enablement.
      `card_transaction.*` carries an

      underscore because the resource is `card_transactions`, a top-level
      resource, not a

      sub-resource of a card. It is not a typo, and there is no
      `card.transaction.*` family, and

      no separate settlement event: settlement is a `status` on
      `card_transaction.updated`.


      **Two states on a dispute report, and neither derives from the other.**
      `filing_state`

      is how far the automated filing with the provider has got. `state` is the
      Dakota operator

      workflow, where `filed_at_vendor` still means a person filed by hand. A
      successful

      automated filing does not move `state`. Read the one you mean.
  - name: Accounts
    description: >-
      Manage account resources used for onramp, offramp, and swap operations.


      **Prerequisites:** Customer must be created and network/asset constraints
      must be known.

      **Related:** Customers, Transactions, Auto Transactions, Info
  - name: Auto Transactions
    description: >-
      Manage automated transaction configurations and execution history for
      account automation workflows.


      **Prerequisites:** Source account must exist and be configured for
      automation.

      **Related:** Accounts, Transactions, Events
  - name: Onboarding
    description: >-
      Manage KYB/KYC onboarding lifecycle, application documents, attestations,
      and verification steps.


      **Prerequisites:** Customer context and required entity/application
      metadata.

      **Related:** Customers, Exceptions, Recipients, Transactions
  - name: Policies
    description: >-
      Define and manage policy objects and rules used for transaction governance
      and risk controls.


      **Prerequisites:** Wallet and signer group resources should be configured
      for enforcement scenarios.

      **Related:** Wallets, Signer Groups, Transactions
  - name: Signer Groups
    description: >-
      Manage signer groups and signer assignments for multi-party authorization
      models.


      **Prerequisites:** Wallets should exist before linking signer groups.

      **Related:** Wallets, Policies, Transactions
  - name: Authentication
    description: >-
      Manage API authentication credentials and key lifecycle for platform
      access.


      **Prerequisites:** Client organization must be provisioned.

      **Related:** Users, Info
  - name: Users
    description: >-
      Manage client users, roles, and identity metadata for platform access
      control.


      **Prerequisites:** Auth credentials and client context must be
      established.

      **Related:** Authentication
  - name: Webhooks
    description: >-
      Manage outbound webhook targets and delivery configuration for event
      notifications.


      **Prerequisites:** Subscriber endpoint must be reachable and secured.

      **Related:** Events, Authentication
  - name: Payouts
    description: >-
      Manage where Dakota sends your accrued developer-fee payouts.


      **Prerequisites:** Auth credentials and client context must be
      established.

      **Related:** Events
  - name: RD Marketing Fee
    description: >-
      Everything behind your RD marketing fee: read what a month came to,
      declare the wallets you hold outside Dakota so the RD in them counts, and
      say where the fee should be sent.


      **Prerequisites:** Client must be in the RD marketing-fee programme. A
      month is readable once it has closed.

      **Related:** Wallets, Events
  - name: Self Serve
    description: >-
      Buy and track prepaid credits, and read the tiers and pricing they are
      sold at.


      **Prerequisites:** Auth credentials and client context must be
      established.

      **Related:** Billing
  - name: Events
    description: >-
      Retrieve event records emitted by platform operations for audit and
      troubleshooting.


      **Prerequisites:** Requesting client must have access to referenced
      resources.

      **Related:** Webhooks, Transactions, Onboarding
  - name: Info
    description: >-
      Read platform capability metadata, such as supported rails, networks, and
      assets.

      These operations are served under `/capabilities/*` - `GET
      /capabilities/countries`

      and `GET /capabilities/networks`. The tag name does not appear in the
      request paths.


      **Prerequisites:** Valid authentication headers.

      **Related:** Accounts, Transactions
  - name: Sandbox
    description: >-
      Trigger sandbox-only simulation endpoints for safe end-to-end integration
      testing with synthetic data. The sandbox host
      (`https://api.platform.sandbox.dakota.xyz`) also accepts a family of
      `X-Sandbox-*` request headers on most write endpoints (`Customers`,
      `Accounts`, `Transactions`, simulate endpoints) that let integrators drive
      deterministic failure modes — pick a preset via `X-Sandbox-Scenario`, or
      compose a custom one with
      `X-Sandbox-Error-Step`/`X-Sandbox-Error-Status`/`X-Sandbox-Error-Message`.
      `X-Sandbox-Instant-Completion` collapses async flows to a single
      synchronous step, and `X-Sandbox-Skip-Auto-Approval` keeps newly created
      KYB applications in `pending` for manual-review testing. All `X-Sandbox-*`
      headers are ignored in production.


      **Prerequisites:** Sandbox environment and test customer data.

      **Related:** Customers, Accounts, Transactions, Onboarding
  - name: Legal
    description: |-
      The legal documents customers accept — terms of service, privacy policy,
      e-sign notice, and partner agreements.

      Dakota publishes these here, and this is the authoritative source: the
      hosted onboarding flow, the dakota.xyz website, and your own integration
      all read the same revisions. Present the current revision to your customer
      before capturing their acceptance so the record reflects the text they
      actually saw.
paths:
  /card_dispute_reports:
    post:
      tags:
        - Cards
      summary: Report a card dispute, and optionally file it
      description: |
        Record that one of your cardholders told you they dispute a card
        transaction, and when they told you.

        **Whether this files a dispute depends on `filing_reason`.**

        - **Send `filing_reason`** and Dakota files the dispute during this
          request, before you get a response. Filing is not reversible through
          this API. You must also send `card_transaction_ids` naming every
          transaction the dispute covers — except for `atm_deposit_missing`,
          the one account-level reason, which requires an empty list.
        - **Omit `filing_reason`** and the report is only recorded. Nothing
          reaches a card network. This is the right call when you cannot yet
          identify the disputed transaction, because a dispute cannot be filed
          without naming one.

        Read `filing_state` on the response to learn which happened. `pending`
        means the dispute was filed and is awaiting the information the network
        requires. `not_filed` means it was not — either because you sent no
        `filing_reason`, or because the filing failed. **A `not_filed` report
        that carries a `filing_reason` needs following up with Dakota:** the
        report is on file and its response clock is running, and because
        `client_reference` is unique you cannot resubmit it.

        In neither case does this endpoint change the card transaction's
        status, reverse an authorization, or move money.

        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.
      operationId: createCardDisputeReport
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        description: The dispute report.
        required: true
        content:
          application/json:
            example:
              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'
            schema:
              $ref: '#/components/schemas/CreateCardDisputeReportRequest'
      responses:
        '201':
          description: >-
            The report was recorded. `state` is `received` when a card
            transaction was named and `awaiting_transaction` when it was not.
          content:
            application/json:
              example:
                id: 33Lm2Xc7Vb9Nq4Rt6Yw8Ze1Ua3S
                card_id: 2tQRvvnYkN6edEJUTmF1LzTj2ug
                card_transaction_id: 2ZFHrqBHb3cTfLVkFSGmHZqdDPi
                client_reference: SUP-48213
                reason: unauthorized
                disputed_amount: '39'
                disputed_currency: USD
                consumer_notified_client_at: '2026-09-18T14:02:11Z'
                client_forwarded_at: '2026-09-18T16:40:00Z'
                state: received
                filing_state: not_filed
                dakota_filed_with_vendor_at: null
                vendor_dispute_reference: null
                rejection_reason: null
                created_at: 1758220800
                updated_at: 1758220800
              schema:
                $ref: '#/components/schemas/CardDisputeReportResponse'
        '400':
          description: |
            Invalid request. Nothing was recorded — fix the request and resend.

            **One exception, when you sent `filing_reason`:** if the report was
            recorded and the card network refused the filing itself, you also
            get a 400. In that case the report IS on file at `filing_state`
            `not_filed`, and resending is answered 409 because the
            `client_reference` is taken. Distinguish the two by resending: a 400
            again means nothing was stored, a 409 means it was.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '401':
          description: Unauthorized
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '403':
          description: Forbidden
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '404':
          description: |
            Not found. Also returned when the named card does not belong to the
            calling client — a card you do not own is indistinguishable from one
            that does not exist.

            **When you sent `filing_reason`** this can also mean the report was
            recorded but the filing found no matching claim, in which case the
            report is on file at `filing_state` `not_filed`. As with 400,
            resending distinguishes them.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '409':
          description: |
            A report with this `client_reference` is already on file for this
            client. The detail names it.

            **When you sent `filing_reason`** this can also mean a dispute has
            already been filed for the report just recorded. Either way, do not
            resubmit: read the existing report instead.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '422':
          description: >-
            Unprocessable — the `X-Idempotency-Key` was already used on this
            endpoint with a different request body

            (problem type `idempotency-key-reused`). The request was not
            executed and the original response was not replayed.

            Resend the original body to receive the original response, or use a
            new key to make a new request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '500':
          description: |
            `#card-dispute-not-fileable`: the filing could not be attempted, and
            NOTHING WAS RECORDED. An identifier Dakota holds for your card or
            for a named transaction is not the shape the card network requires,
            so the filing was refused before the report was written.

            Unlike 502 and 503, no report is on file and no response clock is
            running. Your `client_reference` is still free. Do not resend —
            the request is correct and resending gets the same answer. Contact
            Dakota, who has to repair the stored identifier.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '502':
          description: |
            The report was recorded, but filing it did not succeed. The report
            is on file with `filing_state` of `not_filed` and its response clock
            is running; contact Dakota rather than resubmitting, because the
            `client_reference` is already taken and a resubmission is answered
            with 409.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '503':
          description: |
            Dispute filing is temporarily unavailable. As with 502 the report is
            recorded and `filing_state` is `not_filed`.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
      servers:
        - url: https://api.platform.sandbox.dakota.xyz
          description: Sandbox
components:
  parameters:
    IdempotencyKeyHeader:
      name: x-idempotency-key
      in: header
      required: true
      description: >-
        Unique key (UUID) to ensure request idempotency on POST, PUT and PATCH
        requests.


        A key is scoped to your client, the HTTP method and the path, and is
        remembered for 24 hours after a

        successful (below 400) response. Repeating the same request (same JSON
        body, whatever the key order or

        whitespace) with the same key within that window returns the original
        response with

        `X-Idempotent-Replayed: true` instead of executing the request again.
        Using the same key on the same

        endpoint with a different body returns `422` with problem type
        `idempotency-key-reused`; the request is

        not executed. Error responses (4xx and 5xx) are not remembered, so a
        request refused for a fixable reason

        can be corrected and retried under the same key. Request bodies that are
        not JSON (for example file

        uploads) are not compared.
      schema:
        type: string
        format: uuid
  schemas:
    CreateCardDisputeReportRequest:
      type: object
      title: Create Card Dispute Report Request
      description: |
        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.
      required:
        - card_id
        - client_reference
        - reason
        - consumer_notified_client_at
        - client_forwarded_at
      properties:
        card_id:
          $ref: '#/components/schemas/KSUID'
        card_transaction_id:
          $ref: '#/components/schemas/KSUID'
        card_transaction_ids:
          type: array
          maxItems: 100
          uniqueItems: true
          items:
            $ref: '#/components/schemas/KSUID'
          description: |
            Every Dakota card transaction this dispute covers. Required
            whenever `filing_reason` is sent, except for
            `atm_deposit_missing` — the one account-level reason, which
            disputes a credit that never arrived and must send an empty list.

            One dispute is raised per transaction, so this is the fan-out.
            When you send it, `card_transaction_id` must also be set and must
            be one of these: it stays the single transaction this report is
            anchored to.
          example:
            - 1NFHrqBHb3cTfLVkFSGmHZqdDPi
        filing_reason:
          type: string
          description: |
            The reason to file the dispute under, from the card network's own
            set. Send it to file the dispute; omit it to record the report
            without filing.

            This is NOT the same field as `reason`. `reason` classifies the
            report for your own portfolio reporting and has six values; this
            selects which network rules the case is fought under. Some values
            are spelled the same in both sets and mean different things, so
            they are kept apart deliberately.

            Omitting it stays valid on purpose: a report whose transaction is
            not yet identified cannot be filed, and refusing to record it
            would lose a notice whose response clock is already running.
          enum:
            - card_not_present
            - card_lost
            - card_stolen
            - card_never_received
            - counterfeit
            - account_takeover
            - product_not_received
            - not_as_described
            - credit_not_processed
            - cancelled_recurring
            - paid_by_other_means
            - duplicate_charge
            - late_presentment
            - incorrect_transaction_code
            - no_authorization
            - declined
            - incorrect_amount
            - atm_cash_not_dispensed
            - atm_deposit_wrong_amount
            - atm_deposit_missing
          example: card_not_present
        client_reference:
          type: string
          minLength: 1
          maxLength: 255
          description: |
            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.
          example: SUP-48213
        reason:
          type: string
          description: |
            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.
          enum:
            - unauthorized
            - not_received
            - incorrect_amount
            - duplicate
            - cancelled_recurring
            - other
          example: unauthorized
        description:
          type: string
          maxLength: 4000
          description: |
            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.
          example: >-
            Cardholder says they never authorized this charge and still holds
            the card.
        disputed_amount:
          type: string
          description: |
            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.
          example: '42.50'
        disputed_currency:
          type: string
          description: >-
            ISO 4217 currency code for `disputed_amount`. Required with it, and
            refused without it.
          example: USD
        consumer_notified_client_at:
          type: string
          format: date-time
          description: |
            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.
          example: '2026-09-18T14:02:11Z'
        client_forwarded_at:
          type: string
          format: date-time
          description: When you passed the report to Dakota. Must not be in the future.
          example: '2026-09-18T16:40:00Z'
    CardDisputeReportResponse:
      type: object
      title: Card Dispute Report Response
      description: |
        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.
      required:
        - id
        - card_id
        - client_reference
        - state
        - reason
        - filing_state
        - consumer_notified_client_at
        - client_forwarded_at
        - created_at
        - updated_at
      properties:
        id:
          $ref: '#/components/schemas/KSUID'
        card_id:
          $ref: '#/components/schemas/KSUID'
        card_transaction_id:
          type: string
          nullable: true
          description: >-
            The disputed card transaction, once it is known. Null while it is
            not.
          example: 2B5J8KZ9N7M1K3P6Q8R4T7V9
        filing_state:
          type: string
          description: |
            How far the dispute's filing has got. Always present.

            `not_filed` means Dakota has not filed this dispute — either you
            sent no `filing_reason`, or the filing was attempted and did not
            succeed. In the second case the report is still on file and its
            response clock is running, so a `not_filed` report that names a
            `filing_reason` needs following up.

            The rest report what the provider holds: `pending` is a dispute
            raised whose required information is still outstanding, `filed` is
            submitted, and `refused`, `withdrawn` and `abandoned` are the ways
            it ends without being submitted.
          enum:
            - not_filed
            - pending
            - filed
            - refused
            - withdrawn
            - abandoned
          example: pending
        filing_reason:
          type: string
          nullable: true
          description: |
            The reason the dispute was filed under, as you sent it. Null on a
            report that was recorded without being filed.
          enum:
            - card_not_present
            - card_lost
            - card_stolen
            - card_never_received
            - counterfeit
            - account_takeover
            - product_not_received
            - not_as_described
            - credit_not_processed
            - cancelled_recurring
            - paid_by_other_means
            - duplicate_charge
            - late_presentment
            - incorrect_transaction_code
            - no_authorization
            - declined
            - incorrect_amount
            - atm_cash_not_dispensed
            - atm_deposit_wrong_amount
            - atm_deposit_missing
          example: card_not_present
        provider_filing_accepted_at:
          type: string
          format: date-time
          nullable: true
          description: |
            When Dakota recorded that the dispute was accepted for filing. Null
            until that happens, and it is not restated afterwards.
          example: '2026-09-18T16:41:02Z'
        client_reference:
          type: string
          description: Your own case identifier, as you sent it.
          example: SUP-48213
        state:
          type: string
          description: |
            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.
          enum:
            - received
            - awaiting_transaction
            - filed_at_vendor
            - linked
            - ambiguous
            - rejected
          example: received
        reason:
          type: string
          description: Why the cardholder disputes the transaction, as you sent it.
          enum:
            - unauthorized
            - not_received
            - incorrect_amount
            - duplicate
            - cancelled_recurring
            - other
          example: unauthorized
        disputed_amount:
          type: string
          nullable: true
          description: >-
            The disputed amount in major currency units. Null when the whole
            transaction is disputed.
          example: '42.5'
        disputed_currency:
          type: string
          nullable: true
          description: ISO 4217 currency code for `disputed_amount`.
          example: USD
        consumer_notified_client_at:
          type: string
          format: date-time
          description: When the cardholder told you, as you asserted it.
          example: '2026-09-18T14:02:11Z'
        client_forwarded_at:
          type: string
          format: date-time
          description: When you passed the report to Dakota, as you asserted it.
          example: '2026-09-18T16:40:00Z'
        dakota_filed_with_vendor_at:
          type: string
          format: date-time
          nullable: true
          description: |
            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.
          example: '2026-09-19T09:15:00Z'
        vendor_dispute_reference:
          type: string
          nullable: true
          description: The reference the filing produced, once the report is linked.
          example: dsp_9f2c41
        rejection_reason:
          type: string
          nullable: true
          description: >-
            Why the report ended without a link. Set only when `state` is
            `rejected`.
          example: Cardholder withdrew the report.
        created_at:
          type: integer
          description: >-
            Unix timestamp (seconds) when Dakota recorded the report.
            Server-observed, unlike the two instants you assert.
          example: 1758211200
        updated_at:
          type: integer
          description: Unix timestamp (seconds) of the last change.
          example: 1758297600
    ProblemDetails:
      type: object
      required:
        - type
        - title
        - status
      description: |
        Error response following RFC 9457 Problem Details.
        Public API error responses use this format.
      example:
        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
      properties:
        type:
          type: string
          format: uri
          description: |
            URI reference identifying the problem type.
            Resolves to human-readable documentation.
          example: https://docs.dakota.xyz/api-reference/errors#not-found
        title:
          type: string
          description: >-
            Short, human-readable summary of the problem type. Stable across
            occurrences.
          example: Customer Not Found
        status:
          type: integer
          description: HTTP status code for this occurrence.
          example: 404
        detail:
          type: string
          description: Human-readable explanation specific to this occurrence.
          example: Customer cst_2abc123 was not found in your organization.
        instance:
          type: string
          format: uri
          description: The request path that triggered this error.
          example: https://api.platform.dakota.xyz/customers/cst_2abc123
        request_id:
          type: string
          description: Unique request identifier. Include when contacting support.
          example: req_7f3a8b2c
        errors:
          type: array
          description: Field-level validation errors (present for validation failures).
          items:
            $ref: '#/components/schemas/ValidationError'
        resolution_url:
          type: string
          format: uri
          description: |
            A link the customer can follow to CLEAR this error, present only on
            problems with a concrete self-service remedy.

            Today this is returned by
            `#terms-not-accepted`, where it points at the hosted flow in which
            the outstanding agreement can be signed. The link is token-gated and
            usable as-is — send the customer to it directly rather than parsing
            it out of `detail`.
          example: >-
            https://onboarding.dakota.xyz/applications/2abc123?token=tok_7f3a8b2c
        user_message:
          type: string
          description: |
            A plain-language rendition of `detail` written for the end
            customer, present when one exists for this error. `detail` names
            request fields and actions so a machine caller (such as a payment
            agent drafting proposals) can self-correct; `user_message` says the
            same thing without API vocabulary. Clients that relay errors into a
            human surface (chat, email, UI) should show `user_message` when
            present and fall back to `detail`.
          example: >-
            ACH payments pay out USD, so a USDC payout isn't possible on this
            rail. Change the payout currency to USD and try again.
        reason:
          type: string
          description: >
            A stable, machine-readable code for why the request was refused,

            present only when Dakota has a typed reason for this error. Branch

            on `reason` rather than parsing `detail`.


            When `reason` is a value from the table below other than

            `signature_required` and `immutable_field`, `detail` is text Dakota

            writes for that reason, never a partner's or a bank's wording. For

            those two, `detail` is the text written for that specific refusal.

            In every case the wording can change, so do not parse it.


            This is an open set: new values are added over time and a value is

            never repurposed, so treat an unrecognized `reason` as absent.


            Which operations return it today:


            - `createAccount` (onramp, offramp and swap) and `createTransaction`
              (a one-off transaction creates an account): every value in the
              table except `immutable_field`; `signature_required` comes from
              `createTransaction` only.
            - `updateAccount`: `field_invalid` (a developer fee that is out of
              range), `resource_not_found`, and `immutable_field` (the change
              would alter the account's routing; create a new account instead).
            - `deleteAccount`: `resource_not_found`.

            - `createInstructions`: a payment-agent instruction that creates an
              account fails with the same `reason` values as `createAccount`,
              but `params.field` is never returned there: the response carries
              the other `params` keys only, because this operation has no
              public field names to map to.
            - Other operations may also set `reason`. Treat a `reason` you do
              not recognize as absent, as above, and never assume an operation
              that is not listed here omits it.

            | `reason` | Meaning | `params` |

            | --- | --- | --- |

            | `field_required` | A required request field is missing. | `field`
            |

            | `field_invalid` | A field is present but unusable. | `field`,
            `constraint`, `rail` |

            | `field_too_long` | A field is longer than the rail allows. |
            `field`, `max`, `actual`, `rail` |

            | `field_too_short` | A field is shorter than the rail allows. |
            `field`, `min`, `actual` |

            | `address_incomplete` | An address lacks parts the route needs. |
            `subject`, `fields` |

            | `unsupported_network` | The network is not supported. | `network`
            |

            | `unsupported_asset` | The asset does not exist on the network. |
            `asset`, `network` |

            | `no_route_available` | No payment route covers the request. |
            `direction`, `rail`, `currency`, `network` |

            | `onboarding_required` | The customer has not completed onboarding
            for a capability. | `capability` |

            | `entity_not_active` | Onboarding for a capability exists but is
            not yet usable. | `capability`, `status` |

            | `destination_unreachable` | The destination cannot be reached over
            the requested rail. | `rail`, `alternative`, `direction` |

            | `limit_exceeded` | An amount exceeds a ceiling. | `limit`, `max`,
            `configured`, `currency` |

            | `resource_not_found` | The named resource does not exist. |
            `resource` |

            | `duplicate_resource` | A matching resource already exists. |
            `resource` |

            | `request_rejected` | The request was refused and the reason is not
            disclosed. | none |

            | `signature_required` | The request must be signed. | none |

            | `immutable_field` | The field cannot be changed on an existing
            account; create a new one. | none |
          example: field_too_long
        params:
          type: object
          description: |
            Parameters of `reason`. Every value is a string: a number, a
            token from a closed set, or the public name of a request field
            (`field` is expressed in this operation's request body, and is
            omitted when the offending value has no public name). Never free
            text. Present only alongside `reason`, and only when the reason
            has parameters.
          additionalProperties:
            type: string
          example:
            field: payment_reference
            max: '35'
            actual: '40'
            rail: swift
    KSUID:
      type: string
      title: KSUID
      description: >-
        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.
      pattern: ^[0-9A-Za-z]{27}$
      minLength: 27
      maxLength: 27
      example: 1NFHrqBHb3cTfLVkFSGmHZqdDPi
    ValidationError:
      type: object
      required:
        - field
        - message
      properties:
        field:
          type: string
          description: Field path using dot notation for nested fields.
          example: bank_account.routing_number
        message:
          type: string
          description: Human-readable description of the field error.
          example: Routing number must be exactly 9 digits
        code:
          type: string
          description: Machine-readable error code for this field.
          example: invalid_format
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.