{
  "page": "docs/disputes",
  "title": "Disputes",
  "slug": "disputes",
  "description": "Think a charged result was wrong? Dispute it within 7 days; we decide within 48 hours against the stored result.",
  "section": "Buying results",
  "updated": "2026-09-29",
  "blocks": [
    {
      "type": "p",
      "text": "You pay only for results that pass their published check. A check can still be wrong: an email that was called deliverable bounces, a company record is out of date, an item was charged twice. A dispute is how you tell us. You point at the charged item, say what is wrong, and we compare your claim with the stored copy of the result. If we agree, the charge goes back to your balance and the tool's score takes the hit. This page covers who can dispute, the request, what we compare against, the decision, the 48-hour deadline, how to follow a dispute, the notifications, and the errors."
    },
    {
      "type": "note",
      "text": "Arettic is pre-launch. Keys go to design partners first; everyone else joins the [waitlist](/waitlist). The `@arettic/sdk` and `@arettic/mcp` packages (npm) and the `arettic` package (PyPI) are published at launch. Disputes need a live key: test purchases cost nothing, so there is nothing to dispute."
    },
    {
      "type": "h2",
      "id": "who-can-dispute",
      "text": "What can be disputed, and by whom"
    },
    {
      "type": "p",
      "text": "An item can be disputed when all of these hold:"
    },
    {
      "type": "list",
      "items": [
        "**It was charged.** Only items with a `charged` above 0 on the [receipt](/docs/receipts) qualify: a `passed` result, or a `partial` one charged pro rata. A failed check, a provider error or an expired hold cost you nothing, so there is nothing to dispute. The API answers [not_disputable](/docs/errors#not_disputable).",
        "**It was bought with a live key.** Test keys (`sk_test_…`) buy from mock tools for free and write no receipt. A test key that calls `POST /v1/disputes` gets [invalid_input](/docs/errors#invalid_input): \"Test-mode purchases are free; there's nothing to dispute\".",
        "**It settled less than 7 days ago.** The clock starts at the item's `settled_at` on the receipt. Later than that, the API answers [dispute_window_closed](/docs/errors#dispute_window_closed).",
        "**It has no dispute yet.** One dispute per item, ever. A second attempt answers [conflict](/docs/errors#conflict): \"This item already has a dispute\".",
        "**Your org has fewer than 100 open disputes.** At 100 the API answers [rate_limited](/docs/errors#rate_limited) until some are decided."
      ]
    },
    {
      "type": "p",
      "text": "Four places can file one, and they all create the same dispute:"
    },
    {
      "type": "table",
      "caption": "Ways to open a dispute",
      "head": [
        "From",
        "How",
        "Who"
      ],
      "rows": [
        [
          "Agent key",
          "`POST https://api.arettic.com/v1/disputes`",
          "Any live agent of the org, for any item on the org's receipts."
        ],
        [
          "Org API",
          "`POST https://api.arettic.com/v1/orgs/{orgId}/disputes`",
          "A signed-in member of any role, or an org key (`ok_…`) with write scope. A read-only org key gets [forbidden](/docs/errors#forbidden)."
        ],
        [
          "Dashboard",
          "Receipts, open the receipt, **Dispute** on the item's row (`https://arettic.com/app/receipts/{receiptId}`)",
          "Any member. The button only shows on items that qualify."
        ],
        [
          "MCP",
          "The `open_dispute` tool",
          "Any live agent. Same arguments as the agent key request."
        ]
      ]
    },
    {
      "type": "h2",
      "id": "request",
      "text": "The request"
    },
    {
      "type": "p",
      "text": "Name the item either by its receipt and position, or by its execution. Then say why."
    },
    {
      "type": "table",
      "caption": "Fields of POST /v1/disputes",
      "head": [
        "Field",
        "Type",
        "Required",
        "Notes"
      ],
      "rows": [
        [
          "receipt_id",
          "UUID string",
          "unless execution_id is sent",
          "The receipt the item is on, from the execute response or the [receipt](/docs/receipts)."
        ],
        [
          "item_index",
          "integer, 0 or more",
          "no",
          "The item's position on the receipt (`items[].index`). Default 0, which is the only item of a single-input purchase."
        ],
        [
          "execution_id",
          "UUID string",
          "instead of receipt_id",
          "The item's `execution_id` from the execute response or the receipt. When it is sent, `receipt_id` and `item_index` are ignored."
        ],
        [
          "reason",
          "string",
          "yes",
          "One of the five reasons below."
        ],
        [
          "evidence",
          "string, up to 4,000 characters",
          "when reason is `other`",
          "What is wrong, in your words. Trimmed; anything past 4,000 characters is dropped. The reviewer reads it, and it is shown on the dispute."
        ]
      ]
    },
    {
      "type": "table",
      "caption": "Reasons",
      "head": [
        "reason",
        "Meaning",
        "Label in the dashboard"
      ],
      "rows": [
        [
          "wrong_result",
          "The result passed its check but is not true.",
          "The result is wrong"
        ],
        [
          "invalid_result",
          "The result does not work: the email bounced, the number is dead.",
          "The result doesn't work"
        ],
        [
          "stale_result",
          "The result was true once, not now.",
          "The result is out of date"
        ],
        [
          "duplicate_charge",
          "You were charged twice for the same thing.",
          "Charged twice"
        ],
        [
          "other",
          "Anything else. `evidence` is required.",
          "Something else"
        ]
      ]
    },
    {
      "type": "p",
      "text": "If the item was served by a fallback tool (the receipt's item has `fallback_of`), the dispute lands on the execution that was charged, and the dispute's `tool_id` names that tool. Other agents' purchases count too: any agent of the org can dispute any item on the org's receipts. Another org's receipt answers [not_found](/docs/errors#not_found), the same as an `item_index` that does not exist."
    },
    {
      "type": "h2",
      "id": "examples",
      "text": "Opening a dispute"
    },
    {
      "type": "p",
      "text": "Item 1 of a two-email purchase was called deliverable and bounced. The same call in curl, TypeScript, Python and over MCP:"
    },
    {
      "type": "code",
      "title": "curl",
      "lang": "bash",
      "code": "curl https://api.arettic.com/v1/disputes \\\n  -H \"Authorization: Bearer $ARETTIC_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"receipt_id\": \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n    \"item_index\": 1,\n    \"reason\": \"invalid_result\",\n    \"evidence\": \"Bounced when we sent to it\"\n  }'"
    },
    {
      "type": "code",
      "title": "curl, by execution_id",
      "lang": "bash",
      "code": "curl https://api.arettic.com/v1/disputes \\\n  -H \"Authorization: Bearer $ARETTIC_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"execution_id\": \"c02576cf-b3ce-4b0f-a30c-6e8aad4328ce\", \"reason\": \"invalid_result\" }'"
    },
    {
      "type": "code",
      "title": "TypeScript",
      "lang": "ts",
      "code": "import { Arettic, AretticApiError } from \"@arettic/sdk\";\n\nconst arettic = new Arettic({ apiKey: process.env.ARETTIC_API_KEY });\n\ntry {\n  const dispute = await arettic.openDispute({\n    receipt_id: \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n    item_index: 1, // or { execution_id: \"…\" } instead of receipt_id + item_index\n    reason: \"invalid_result\",\n    evidence: \"Bounced when we sent to it\",\n  });\n  console.log(dispute.dispute_id, dispute.status, dispute.decide_by); // \"open\", 48 hours from now\n} catch (err) {\n  if (err instanceof AretticApiError) {\n    // \"not_disputable\", \"dispute_window_closed\", \"conflict\", \"not_found\", \"invalid_input\"…\n    console.error(err.status, err.code, err.message);\n  }\n  throw err;\n}"
    },
    {
      "type": "code",
      "title": "Python",
      "lang": "python",
      "code": "from arettic import Arettic, AretticApiError\n\nclient = Arettic()  # reads ARETTIC_API_KEY (and ARETTIC_API_URL, if set)\n\ntry:\n    dispute = client.open_dispute(\n        receipt_id=\"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n        item_index=1,  # or execution_id=\"…\" instead of receipt_id + item_index\n        reason=\"invalid_result\",\n        evidence=\"Bounced when we sent to it\",\n    )\nexcept AretticApiError as err:\n    # \"not_disputable\", \"dispute_window_closed\", \"conflict\", \"not_found\", \"invalid_input\"...\n    print(err.status, err.code, err.message)\n    raise\n\nprint(dispute[\"dispute_id\"], dispute[\"status\"], dispute[\"decide_by\"])  # \"open\", 48 hours from now"
    },
    {
      "type": "code",
      "title": "MCP tool call",
      "lang": "json",
      "code": "{\n  \"name\": \"open_dispute\",\n  \"arguments\": {\n    \"receipt_id\": \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n    \"item_index\": 1,\n    \"reason\": \"invalid_result\",\n    \"evidence\": \"Bounced when we sent to it\"\n  }\n}"
    },
    {
      "type": "p",
      "text": "Over MCP, `open_dispute` takes `receipt_id` and `item_index` only (no `execution_id`); `item_index` defaults to 0. The tool result is the same JSON as the REST response, as text content. The API answers `201 Created` with the dispute:"
    },
    {
      "type": "code",
      "title": "Response (example)",
      "lang": "json",
      "code": "{\n  \"dispute_id\": \"a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30\",\n  \"status\": \"open\",\n  \"receipt_id\": \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n  \"item_index\": 1,\n  \"execution_id\": \"c02576cf-b3ce-4b0f-a30c-6e8aad4328ce\",\n  \"tool_id\": \"hunter-verify-email\",\n  \"reason\": \"invalid_result\",\n  \"evidence\": \"Bounced when we sent to it\",\n  \"charged\": { \"credits\": \"7\", \"usd\": \"0.007\" },\n  \"refunded\": { \"credits\": \"0\", \"usd\": \"0.000\" },\n  \"opened_at\": \"2026-09-29T10:12:03.417Z\",\n  \"decide_by\": \"2026-10-01T10:12:03.417Z\",\n  \"decided_at\": null\n}"
    },
    {
      "type": "p",
      "text": "From the org API the request body is the same, at `POST /v1/orgs/{orgId}/disputes`. With the SDKs: `new AretticOrg({ orgId }).disputes.create({ … })` and `AretticOrg(org_id=…).disputes.create(…)`. See [Org API](/docs/org-api)."
    },
    {
      "type": "h2",
      "id": "dispute-object",
      "text": "The dispute object"
    },
    {
      "type": "p",
      "text": "Every dispute endpoint returns the same object. Money is `{ \"credits\": \"7\", \"usd\": \"0.007\" }`, as everywhere else in the API. Times are ISO 8601 in UTC."
    },
    {
      "type": "table",
      "caption": "Fields of a dispute",
      "head": [
        "Field",
        "Meaning"
      ],
      "rows": [
        [
          "dispute_id",
          "The dispute's UUID. Use it with `GET /v1/disputes/{id}`."
        ],
        [
          "status",
          "`open` until we decide, then `upheld` (refunded) or `rejected` (the charge stands). It never changes again after that."
        ],
        [
          "receipt_id",
          "The receipt the item is on."
        ],
        [
          "item_index",
          "The item's position on that receipt."
        ],
        [
          "execution_id",
          "The charged execution behind the item. After a fallback, the one that served it."
        ],
        [
          "tool_id",
          "The tool that produced the disputed result."
        ],
        [
          "reason",
          "The reason you gave."
        ],
        [
          "evidence",
          "Your evidence, or `null`."
        ],
        [
          "charged",
          "What the item cost you. This is the most an upheld dispute refunds."
        ],
        [
          "refunded",
          "What has been refunded for this dispute: 0 while open or rejected, the item's charge once upheld."
        ],
        [
          "opened_at",
          "When the dispute was filed."
        ],
        [
          "decide_by",
          "48 hours after `opened_at`. Our deadline; past it the dispute is upheld automatically."
        ],
        [
          "decided_at",
          "When it was decided, or `null` while open."
        ],
        [
          "decision_note",
          "Present once decided and a note was written. Every rejection has one, because we must say why. An automatic uphold says \"Upheld automatically: not decided within 48 hours\"."
        ]
      ]
    },
    {
      "type": "h2",
      "id": "what-we-compare-against",
      "text": "What we compare against"
    },
    {
      "type": "p",
      "text": "Every live purchase's input and result are stored encrypted with your org's own key, for 7 days, then hard-deleted. That copy is what a dispute is decided against. Opening a dispute puts a hold on the item's copy so it outlives the 7 days: it is kept until the dispute is decided, and at most 48 hours beyond the usual 7 days. Once decided, the hold lifts and the normal retention applies again."
    },
    {
      "type": "p",
      "text": "The reviewer sees your reason and evidence, the stored input and result, the result's hash, the check and its version, and the reason the check recorded. Every look at a stored copy is logged with who looked, which dispute it was for, and whether the copy was still there. The copy is not shared with the provider or anyone outside Arettic. If you asked for your org's data to be deleted before the dispute was reviewed, the copy is gone, and the reviewer is told so instead of seeing a result. [Data handling](/docs/data-handling) has the retention rules in full."
    },
    {
      "type": "h2",
      "id": "decision",
      "text": "The decision"
    },
    {
      "type": "table",
      "caption": "The two outcomes",
      "head": [
        "status",
        "What happens"
      ],
      "rows": [
        [
          "upheld",
          "The item's charge goes back to your balance, to the same paid or trial credits it was taken from, as a `refund` entry on the ledger that references the dispute. The dispute's `refunded` becomes the item's `charged`, the receipt's `refunded` total grows by the same amount, and the item's `dispute.refunded` on the receipt shows it. The upheld dispute counts against the tool's score."
        ],
        [
          "rejected",
          "The charge stands. The reviewer has to write a `decision_note` saying why, and you see it on the dispute, in the dashboard and in the email. Nothing changes on the receipt except the item's `dispute.status`."
        ]
      ]
    },
    {
      "type": "p",
      "text": "A dispute is decided once. Receipts never change; a refund is added on top, so the receipt's `charged` still says what you paid at the time and `refunded` says what came back. If the same item was somehow refunded already, the uphold is refused rather than paid twice."
    },
    {
      "type": "h2",
      "id": "sla",
      "text": "48 hours, then automatic uphold"
    },
    {
      "type": "p",
      "text": "We decide within 48 hours of `opened_at`; `decide_by` is that moment. An hourly job upholds every open dispute past its `decide_by`, with the note \"Upheld automatically: not decided within 48 hours\", and refunds it like any other uphold. You never wait on us longer than 48 hours, and you never need to chase a dispute: if nobody looked at it, you get the refund."
    },
    {
      "type": "h2",
      "id": "following",
      "text": "Following a dispute"
    },
    {
      "type": "p",
      "text": "A dispute shows up in four places as soon as it is filed:"
    },
    {
      "type": "list",
      "items": [
        "`GET https://api.arettic.com/v1/disputes/{id}` with any agent key of the org: the dispute object above.",
        "`GET https://api.arettic.com/v1/orgs/{orgId}/disputes` with a session or an org key: `{ \"disputes\": [ … ] }`, open ones first, newest first, up to 500. Add `?status=open`, `upheld` or `rejected` to filter. This list is not available to agent keys.",
        "The receipt: the item gets a `dispute` field with `dispute_id`, `status` and `refunded`, on `GET /v1/receipts/{id}` and the org receipt endpoints. Items without a dispute have no `dispute` field.",
        "The dashboard: `https://arettic.com/app/disputes` lists every dispute with its reason, charge, status, deadline, decision time, refund and decision note, with filters for open, upheld and rejected."
      ]
    },
    {
      "type": "code",
      "title": "curl",
      "lang": "bash",
      "code": "# One dispute, with an agent key\ncurl https://api.arettic.com/v1/disputes/a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30 \\\n  -H \"Authorization: Bearer $ARETTIC_API_KEY\"\n\n# The org's open disputes, with an org key\ncurl \"https://api.arettic.com/v1/orgs/0f4e7c2a-91b3-4d6e-8a5f-3c2b1d0e9f87/disputes?status=open\" \\\n  -H \"Authorization: Bearer $ARETTIC_ORG_KEY\""
    },
    {
      "type": "code",
      "title": "TypeScript",
      "lang": "ts",
      "code": "import { Arettic, AretticOrg } from \"@arettic/sdk\";\n\nconst arettic = new Arettic({ apiKey: process.env.ARETTIC_API_KEY });\nconst dispute = await arettic.dispute(\"a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30\");\nif (dispute.status === \"upheld\") console.log(\"refunded\", dispute.refunded.credits);\nif (dispute.status === \"rejected\") console.log(\"kept, because:\", dispute.decision_note);\n\n// The org's list needs an org key (ok_…), not an agent key.\nconst org = new AretticOrg({ apiKey: process.env.ARETTIC_ORG_KEY, orgId: \"0f4e7c2a-91b3-4d6e-8a5f-3c2b1d0e9f87\" });\nconst open = await org.disputes.list({ status: \"open\" });\nconsole.log(open.length, \"waiting for a decision\");"
    },
    {
      "type": "code",
      "title": "Python",
      "lang": "python",
      "code": "import os\nfrom arettic import Arettic, AretticOrg\n\nclient = Arettic()\ndispute = client.dispute(\"a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30\")\nif dispute[\"status\"] == \"upheld\":\n    print(\"refunded\", dispute[\"refunded\"][\"credits\"])\nelif dispute[\"status\"] == \"rejected\":\n    print(\"kept, because:\", dispute.get(\"decision_note\"))\n\n# The org's list needs an org key (ok_...), not an agent key.\norg = AretticOrg(api_key=os.environ[\"ARETTIC_ORG_KEY\"], org_id=\"0f4e7c2a-91b3-4d6e-8a5f-3c2b1d0e9f87\")\nopen_disputes = org.disputes.list(status=\"open\")[\"disputes\"]\nprint(len(open_disputes), \"waiting for a decision\")"
    },
    {
      "type": "code",
      "title": "Response (example)",
      "lang": "json",
      "code": "{\n  \"dispute_id\": \"a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30\",\n  \"status\": \"upheld\",\n  \"receipt_id\": \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n  \"item_index\": 1,\n  \"execution_id\": \"c02576cf-b3ce-4b0f-a30c-6e8aad4328ce\",\n  \"tool_id\": \"hunter-verify-email\",\n  \"reason\": \"invalid_result\",\n  \"evidence\": \"Bounced when we sent to it\",\n  \"charged\": { \"credits\": \"7\", \"usd\": \"0.007\" },\n  \"refunded\": { \"credits\": \"7\", \"usd\": \"0.007\" },\n  \"opened_at\": \"2026-09-29T10:12:03.417Z\",\n  \"decide_by\": \"2026-10-01T10:12:03.417Z\",\n  \"decided_at\": \"2026-09-30T08:40:19.052Z\"\n}"
    },
    {
      "type": "p",
      "text": "There is no MCP tool for reading a dispute. An agent on MCP can call `get_receipt` and read the item's `dispute` field instead."
    },
    {
      "type": "h2",
      "id": "notifications",
      "text": "When it is decided"
    },
    {
      "type": "p",
      "text": "A decision, by a person or by the 48-hour job, sends one `dispute.decided` event. It goes to every [webhook](/docs/webhooks) of the org that subscribes to it (or to all events), signed with the endpoint's secret, and as an email to the org's owners. Nothing is sent when a dispute is opened."
    },
    {
      "type": "code",
      "title": "Webhook body (example)",
      "lang": "json",
      "code": "{\n  \"id\": \"5b2c8e1f-7a3d-4f9e-b6c0-1d4a2e8f7c93\",\n  \"type\": \"dispute.decided\",\n  \"created_at\": \"2026-09-30T08:40:19.052Z\",\n  \"data\": {\n    \"dispute_id\": \"a3d9e2b1-5c7f-4e08-9b6d-2f1c8a7e4d30\",\n    \"receipt_id\": \"67a1fb46-c554-4cf6-b4e2-df1dbdf0e936\",\n    \"item_index\": 1,\n    \"decision\": \"upheld\",\n    \"refunded_credits\": \"7\",\n    \"note\": null\n  }\n}"
    },
    {
      "type": "p",
      "text": "`decision` is `upheld` or `rejected`; `refunded_credits` is a whole number of credits as a string, `\"0\"` on a rejection; `note` is the decision note or `null`. The email's subject is \"Your dispute was upheld\" or \"Your dispute was rejected\", and its body names the receipt and item and, on an uphold, the credits refunded. Poll `GET /v1/disputes/{id}` if you would rather not run a webhook: the status changes at the same moment."
    },
    {
      "type": "h2",
      "id": "score-effect",
      "text": "What an upheld dispute does to a tool's score"
    },
    {
      "type": "p",
      "text": "Disputes are the D input of every tool's [score](/docs/scores). For each tool and region, at the weekly recompute, D is the number of disputes upheld in the last 28 days divided by the number of live results that passed (or partially passed) in the last 28 days. The score loses `min(20, 500 × D)` points: one upheld dispute per 100 passed results costs 5 points, and one per 25 or worse costs the maximum 20. Rejected disputes do not count. A score moves at most 10 points a week, so a wave of upheld disputes shows over a few weeks unless the tool is paused, and D is published next to the score with the other inputs."
    },
    {
      "type": "p",
      "text": "This is why we review disputes rather than refund on request: an upheld dispute is a signal to every buyer of that tool, so it has to be right."
    },
    {
      "type": "h2",
      "id": "test-mode",
      "text": "Test mode"
    },
    {
      "type": "note",
      "text": "A test key cannot dispute. Test purchases run against mock providers, cost nothing and write no receipt, so `POST /v1/disputes` and the `open_dispute` tool answer `400` [invalid_input](/docs/errors#invalid_input) with \"Test-mode purchases are free; there's nothing to dispute\". Use a live key and a charged item to try the flow end to end. See [Test mode](/docs/test-mode)."
    },
    {
      "type": "h2",
      "id": "errors",
      "text": "Errors"
    },
    {
      "type": "p",
      "text": "Every refusal is `{ \"error\": { \"code\", \"message\", \"doc_url\", \"retryable\" } }`, and the SDKs raise it as `AretticApiError` with the same fields. The codes a dispute request can get:"
    },
    {
      "type": "table",
      "caption": "Error codes on the dispute endpoints",
      "head": [
        "Code",
        "HTTP",
        "When"
      ],
      "rows": [
        [
          "[invalid_input](/docs/errors#invalid_input)",
          "400",
          "A test key filed; `reason` is not one of the five; `reason` is `other` without `evidence`; neither a valid `execution_id` nor a valid `receipt_id` with a whole-number `item_index` was sent. The message names the problem."
        ],
        [
          "[not_found](/docs/errors#not_found)",
          "404",
          "No item with that `receipt_id` and `item_index` (or that `execution_id`) on your org's receipts, or, on a GET, no dispute with that id in your org."
        ],
        [
          "[not_disputable](/docs/errors#not_disputable)",
          "409",
          "The item was not charged: nothing to refund."
        ],
        [
          "[dispute_window_closed](/docs/errors#dispute_window_closed)",
          "409",
          "The item settled more than 7 days ago."
        ],
        [
          "[conflict](/docs/errors#conflict)",
          "409",
          "The item already has a dispute."
        ],
        [
          "[rate_limited](/docs/errors#rate_limited)",
          "429",
          "Your org already has 100 open disputes. Wait for decisions."
        ],
        [
          "[unauthenticated](/docs/errors#unauthenticated)",
          "401",
          "No key, or a revoked one."
        ],
        [
          "[forbidden](/docs/errors#forbidden)",
          "403",
          "A read-only org key tried to file, or an org key was used on another org's path."
        ]
      ]
    },
    {
      "type": "code",
      "title": "Response (example)",
      "lang": "json",
      "code": "{\n  \"error\": {\n    \"code\": \"dispute_window_closed\",\n    \"message\": \"Disputes must be opened within 7 days of the purchase\",\n    \"doc_url\": \"https://arettic.com/docs/errors#dispute_window_closed\",\n    \"retryable\": false\n  }\n}"
    },
    {
      "type": "h2",
      "id": "see-also",
      "text": "See also"
    },
    {
      "type": "list",
      "items": [
        "[Receipts](/docs/receipts): where `receipt_id`, `item_index`, `execution_id`, `settled_at` and the item's `dispute` field live.",
        "[Scores](/docs/scores): the formula, and D next to the other five inputs.",
        "[Webhooks](/docs/webhooks): subscribing to `dispute.decided`, the signature and retries.",
        "[Data handling](/docs/data-handling): the stored copy, its 7 days, and the hold a dispute puts on it.",
        "[Error codes](/docs/errors): every code, with its status and fix."
      ]
    }
  ]
}