---
title: "Register a dispute webhook"
method: POST
path: "/api/v1/dispute-webhooks"
tags: ["Dispute webhooks"]
---

# Register a dispute webhook

`POST /api/v1/dispute-webhooks`

## Request

- Base URL: `https://api.tabby.ai`
- URL: `https://api.tabby.ai/api/v1/dispute-webhooks`
- Auth: HTTP bearer

Registers a dispute webhook for the merchant identified by the secret key and the
`X-Merchant-Code` header. Disputes have no test mode: authorize with a production
secret key (`sk_...`) — a request signed with a test key (`sk_test_...`) is rejected
with `403`. Each `merchant_code` can have up to 4 dispute webhooks; the limit is
separate from payment webhooks. The `url` is normalised before it is stored
(lower-case scheme and host, default port and trailing slash removed) and must be
unique per merchant. `header.value` is a secret: it is accepted in full and returned
masked in every response, including this one — `****` followed by the last 4 characters
for values longer than 8 characters, `****` alone for shorter values.

## Headers

- `X-Merchant-Code` string, required

## Request body

- DisputeWebhookRequest
  - `url` string, uri, required: Endpoint for dispute notifications (HTTPS recommended). Must be an absolute URL with a publicly resolvable host name — `localhost`, raw IP addresses and hosts that do not resolve are rejected. Normalised before it is stored (lower-case scheme and host, default port and trailing slash removed) and unique per merchant.
  - `header` object: Optional static header Tabby adds to every notification so you can verify its origin. Omit it on `PUT` to remove the header.
    - `title` string, required: Header name (an HTTP token, up to 128 characters).
    - `value` string, required: Header value (up to 1024 characters). Treated as a secret — every response returns it masked.

## Response `200`

Success. Dispute webhook object is returned; `header.value` is masked.

- DisputeWebhook
  - `id` string, required: Unique dispute webhook ID, assigned by Tabby.
  - `url` string, uri, required: Endpoint for dispute notifications, as stored (normalised).
  - `header` object, nullable: The signing header, if one was registered. `value` is masked.
    - `title` string
    - `value` string: Masked — `****` followed by the last 4 characters of the stored value; `****` alone when the value has 8 characters or fewer.

## Other responses

- `400`: One of the required fields is missing or request is not formatted correctly.
- `401`: The request cannot be authorized.
- `403`: Disputes have no test mode — the request was authorized with a test secret key.
- `500`: Something bad happened. We're notified.

## Changes

- **2026-09-24** `33b6fd80a009`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/tabby/apis/tabby-api-reference/changes/api/v1/dispute-webhooks/post.md)

---

[API](https://skmtc.dev/tabby/apis/tabby-api-reference.md) - [All operations](https://skmtc.dev/tabby/apis/tabby-api-reference/llms.txt) - [OpenAPI document](https://skmtc.dev/tabby/apis/tabby-api-reference/revisions/ca3b26b83f76?raw)
