> This page is for version v1 (default).
> For other versions, use one of these documentation indexes:
> - v1 (default): https://developers.truemed.com/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.truemed.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.truemed.com/_mcp/server.

# Update Dispute Metadata

POST https://dev-api.truemed.com/api/v1/disputes/{business_id}/metadata
Content-Type: application/json

Attach your own metadata to a dispute — an internal case ID, the teammate who owns it, a link to your evidence workspace, free-form notes — so you can correlate Truemed disputes with your own systems.

This is a **full replace**, not a merge: the `metadata` object you send overwrites whatever was stored, so include every key you want to keep. Metadata is the only writable part of a dispute; its state, phase, reason, amounts, and deadlines are owned by the processor and are read-only. Scoped to your sales channel — you can only update metadata on your own disputes.

Reference: https://developers.truemed.com/api-reference/disputes/update-dispute-metadata

## Authentication

- `x-truemed-api-key` header (required) — Sales channel API key for merchant server-to-server authentication

## Servers

- `https://dev-api.truemed.com` (Development server, default)
- `https://api.truemed.com` (Production server)

## Request

### Path parameters

- `business_id` (string, required) — The Truemed dispute ID (UUID).

### Body (application/json)

This endpoint expects a DisputeMetadataRequest.

- `metadata` (map from string to any, required) — Replaces the dispute's metadata. Only metadata is mutable; state/amounts/deadlines are read-only.

## Response

### 200

Successful response

- `amount` (integer, required) — The original disputed amount in cents, independent of resolution.
- `created_at` (datetime, required) — When the dispute was created.
- `currency` (string, required) — ISO currency code of the disputed amount.
- `dispute_id` (string, required) — Stable Truemed dispute ID (UUID). Use this as the dispute's identifier.
- `processor` (enum, required) — Payment processor the dispute originated from.
  - Allowed values: `STRIPE`, `FAKE`, `EXTERNAL`
- `processor_dispute_id` (string, required) — Raw payment-processor dispute ID (e.g. Stripe `du_…`), for reconciliation.
- `reason` (enum, required) — Canonical reason the dispute was filed.
  - Allowed values: `credit_not_processed`, `duplicate`, `fraudulent`, `general`, `noncompliant`, `product_not_received`, `product_unacceptable`, `subscription_canceled`, `unrecognized`
- `state` (enum, required) — Canonical dispute state.
  - Allowed values: `inquiry`, `needs_response`, `under_review`, `won`, `lost`, `accepted`, `expired`, `closed`
- `counters` (list of CounterResource, optional, default: []) — Evidence counters for this dispute (the full chain across phases).
- `due_by` (datetime, optional, nullable) — Evidence submission deadline, if the dispute is challengeable.
- `metadata` (map from string to any, optional, default: {}) — Arbitrary merchant-set metadata.
- `network_reason_code` (string, optional, nullable) — Raw card-network reason code behind the dispute (e.g. Visa `10.4`), if provided.
- `outcome` (enum, optional, nullable) — Terminal outcome; null until the dispute resolves.
  - Allowed values: `won`, `lost`, `accepted`, `expired`, `closed`
- `payment_session_id` (string, optional, nullable) — The Truemed payment session this dispute belongs to. Null for disputes on non-payment-session charges.
- `phase` (enum, optional, nullable) — Which round of the dispute (inquiry, dispute, pre-arbitration, arbitration).
  - Allowed values: `inquiry`, `dispute`, `pre_arbitration`, `arbitration`
- `prior_dispute_id` (string, optional, nullable) — Truemed dispute ID (UUID) of the prior round in a pre-arbitration/re-filing chain, if any.
- `resolved_at` (datetime, optional, nullable) — When the dispute reached a terminal state.

## Errors

### 400 Bad Request Error

Bad Request

- `error` (enum, required)
  - Allowed values: `TotalAmountInvalid`, `ValidationError`
- `message` (string, required)

### 404 Not Found Error

Not Found

- `error` (enum, required)
  - Allowed values: `NotFound`
- `message` (string, required)

### 405 Method Not Allowed Error

Method Not Allowed

- `error` (enum, required)
  - Allowed values: `MethodNotAllowed`
- `message` (string, required)

### 500 Internal Server Error

Internal Server Error

- `error` (enum, required)
  - Allowed values: `ServerError`
- `message` (string, required)

### 501 Not Implemented Error

Not Implemented

- `error` (enum, required)
  - Allowed values: `NotImplemented`
- `message` (string, required)

## Types

### CounterResource

- `counter_id` (string, required) — Stable Truemed counter ID (UUID).
- `created_at` (datetime, required) — When this counter was created.
- `phase` (enum, required) — Dispute phase this counter responds to.
  - Allowed values: `inquiry`, `dispute`, `pre_arbitration`, `arbitration`
- `revision` (integer, required) — Optimistic-lock revision; echo it back on the next draft save to detect conflicts.
- `state` (enum, required) — Counter lifecycle state.
  - Allowed values: `draft`, `submitted`, `withdrawn`, `superseded`
- `updated_at` (datetime, required) — When this counter was last updated.
- `evidence_items` (list of EvidenceItem, optional, default: []) — The categorized evidence captured on this counter.
- `submitted_at` (datetime, optional, nullable) — When this counter was submitted to the processor.
- `submitted_by` (string, optional, nullable) — Email of the dashboard user who submitted this counter; null for drafts or API-key submissions.

### EvidenceItem

- `category` (enum, required) — Canonical evidence category; the adapter maps it to the processor's evidence fields.
  - Allowed values: `product_description`, `customer_communication`, `customer_name`, `customer_email`, `customer_purchase_ip`, `customer_signature`, `billing_address`, `receipt`, `shipping_documentation`, `shipping_tracking_number`, `service_documentation`, `service_date`, `access_activity_log`, `refund_policy`, `refund_policy_disclosure`, `refund_refusal_explanation`, `cancellation_policy`, `cancellation_policy_disclosure`, `cancellation_rebuttal`, `duplicate_charge_documentation`, `duplicate_charge_explanation`, `uncategorized`
- `file_ids` (list of string, optional, default: []) — File IDs (from the Files API) attached for this category; must be owned by you.
- `text` (string, optional, nullable) — Free-text evidence for this category.

## Examples

**Request**

```json
{}
```

**Response**

```json
{
  "amount": 1,
  "created_at": "2024-01-15T09:30:00Z",
  "currency": "string",
  "dispute_id": "string",
  "processor": "STRIPE",
  "processor_dispute_id": "string",
  "reason": "credit_not_processed",
  "state": "inquiry",
  "counters": [
    {
      "counter_id": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "phase": "inquiry",
      "revision": 1,
      "state": "draft",
      "updated_at": "2024-01-15T09:30:00Z",
      "evidence_items": [
        {
          "category": "product_description",
          "file_ids": [
            "string"
          ],
          "text": "string"
        }
      ],
      "submitted_at": "2024-01-15T09:30:00Z",
      "submitted_by": "string"
    }
  ],
  "due_by": "2024-01-15T09:30:00Z",
  "metadata": {},
  "network_reason_code": "string",
  "outcome": "won",
  "payment_session_id": "string",
  "phase": "inquiry",
  "prior_dispute_id": "string",
  "resolved_at": "2024-01-15T09:30:00Z"
}
```

**SDK Code**

```python
import requests

url = "https://dev-api.truemed.com/api/v1/disputes/business_id/metadata"

payload = {}
headers = {
    "x-truemed-api-key": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://dev-api.truemed.com/api/v1/disputes/business_id/metadata';
const options = {
  method: 'POST',
  headers: {'x-truemed-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```