API REFERENCE v1

RETENTION

Chargebacks

The Dispute object

Disputes and early fraud warnings: evidence, replies and refunds.

ATTRIBUTES

Show 23 more attributesHide 23 attributes
  • customer_name string | null
  • customer_email string | null
  • customer_plan string | null

    Plan of the customer's latest subscription in this mode.

  • amount_cents integer
  • currency string
  • reason string | null
  • status enum
    • needs_response
    • under_review
    • won
    • lost
    • accepted
    • warning_needs_response
    • warning_under_review
    • warning_closed
    • prevented
    • no_decision
  • evidence_due_by string | null date-time
  • opened_at string | null date-time
  • outcome_at string | null date-time
  • submitted_at string | null date-time
  • submitted_by string | null

    usr_… or system (auto-submit).

  • The provider already has a reply (Stripe Smart Disputes, its dashboard): NoChurn will not send.

  • read_only boolean

    Nothing can be sent or edited: closed, submitted, or handled by the provider.

  • capability enum
    • evidence_api
    • provider_handles
    • refund_review
    • none
  • evidence_count integer
  • draft_status enum | null
    • draft
    • approved
    • sent
  • win_score object | null

    Chance of winning, 0–100: the AI's estimate from the evidence (an estimate, not a measured probability), or a person's (source manual). Null until estimated.

    Show child attributesHide child attributes
  • created_at string date-time
  • evidence array of objects
    Show child attributesHide child attributes
    • id string
    • object enum
      • dispute_evidence_item
    • kind enum
      • communication
      • policy
      • usage
      • reminder
      • cancel_history
      • refund_history
      • receipt
      • other
    • title string
    • content string | null
    • source_type string | null
    • source_id string | null
    • occurred_at string | null date-time
    • included boolean
    • position integer
    • file object | null

      A file attached by a person (source_type file): PDF, JPEG or PNG, 5 MB at most. null for other evidence.

      Show child attributesHide child attributes
  • draft object | null
    Show child attributesHide child attributes
  • charge_details object | null

    The disputed charge as NoChurn synced it; null when the payment is unknown.

    Show child attributesHide child attributes
  • recommendation object | null

    Whether contesting is worth it; null once nothing can be sent. A suggestion only: NoChurn never accepts by itself.

    Show child attributesHide child attributes
    • suggestion enum | null

      accept: no evidence from a record and the amount is at most the cost of contesting. null: not enough to compare.

      • accept
      • contest
    • reason string
    • evidence_count integer

      Included evidence backed by a record (NoChurn's own statements excluded).

    • amount_cents integer | null

      Disputed amount in currency; null without an exchange rate.

    • contest_cost_cents integer | null

      From disputes_settings; null when not set.

    • currency string
    • win_score integer | null

      Chance of winning used (AI or a person).

    • expected_gain_cents integer | null

      Chance × amount, compared with the cost of contesting; null without a score and a cost.

Schema: DisputeDetail

THE DISPUTE OBJECT
{
  "id": "dsp_Na6rvG7ku8MtRaDv",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_mLiVFHx89vq9XnXZ",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_64GTYRa6AoYRm1H7",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 3,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_RfiKG9mqpf14mwbe",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_AkhDCxNfD6Kt6Gd9",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    },
    {
      "id": "dev_jTobuAp3akY663Wa",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Terms accepted at signup",
      "content": "File attached by the merchant: terms.pdf (PDF, 51 Bytes).",
      "source_type": "file",
      "source_id": "9df4060a-9560-4835-9636-af43eaf834e7",
      "occurred_at": "2026-11-04T10:00:00Z",
      "included": true,
      "position": 3,
      "file": {
        "filename": "terms.pdf",
        "content_type": "application/pdf",
        "byte_size": 51,
        "sent_to_provider": false
      }
    }
  ],
  "draft": {
    "id": "ddr_VxjQntJkeR1w9xhb",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_RfiKG9mqpf14mwbe", "dev_AkhDCxNfD6Kt6Gd9"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": "contest",
    "reason": "1 piece of evidence from NoChurn's records.",
    "evidence_count": 1,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

A dispute with its evidence and draft

  • Secret key (nc_test_… or nc_live_…). Restricted keys need read access.
  • AI apps (OAuth): read scope.

PATH PARAMETERS

  • id string REQUIRED

RETURNS

ERRORS

GET/v1/disputes/{id}
curl https://api.nochurn.sh/v1/disputes/dsp_nu5bHBnJb3n4KEEQ \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_nu5bHBnJb3n4KEEQ", {
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const dispute = await res.json();
import requests

res = requests.get(
    "https://api.nochurn.sh/v1/disputes/dsp_nu5bHBnJb3n4KEEQ",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_nu5bHBnJb3n4KEEQ")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_nu5bHBnJb3n4KEEQ",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_37LhkkzpDAwwa5cU",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_JzQ8sUdXtXqzqq7x",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_iqCLHm6bhLAX1ZDa",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_kgW2ZRLXZHVnuFmk",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_GoqrRZdQYbEjCerZ",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_iqCLHm6bhLAX1ZDa", "dev_kgW2ZRLXZHVnuFmk"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": null,
    "reason": "No evidence from a record. Set the cost of contesting in Chargebacks › Settings to compare it with the amount.",
    "evidence_count": 0,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Disputes

  • Secret key (nc_test_… or nc_live_…). Restricted keys need read access.
  • AI apps (OAuth): read scope.

QUERY PARAMETERS

  • status string

    Comma separated statuses.

  • provider string
  • due_before string date-time
  • customer string
  • sort enum default "opened_at"

    opened_at: newest first. evidence_due_by: soonest deadline first, disputes without a deadline last.

    • opened_at
    • evidence_due_by
  • limit integer 1 to 100

RETURNS

GET/v1/disputes
curl https://api.nochurn.sh/v1/disputes \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/disputes", {
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const page = await res.json();
import requests

res = requests.get(
    "https://api.nochurn.sh/v1/disputes",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
page = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
page = JSON.parse(res.body)
RESPONSE 200
{
  "object": "list",
  "data": [
    {
      "id": "dsp_2F9vssKp8BhfWwe9",
      "object": "dispute",
      "livemode": false,
      "provider": "stripe",
      "billing_connection": "scn_VDpCSHRTXyhtofFq",
      "external_id": "dp_1",
      "charge": "ch_1",
      "customer": "cst_5B4srTLYwe9m6DyR",
      "customer_name": "Lena",
      "customer_email": "customer1@acme-corp.dev",
      "customer_plan": "Pro",
      "amount_cents": 4900,
      "currency": "eur",
      "reason": "subscription_canceled",
      "status": "needs_response",
      "evidence_due_by": "2026-11-09T10:00:00Z",
      "opened_at": "2026-11-04T10:00:00Z",
      "outcome_at": null,
      "submitted_at": null,
      "submitted_by": null,
      "provider_submitted": false,
      "read_only": false,
      "capability": "evidence_api",
      "evidence_count": 2,
      "draft_status": "draft",
      "win_score": null,
      "created_at": "2026-11-04T10:00:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Counts of the Disputes tab (each with its sample size)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need read access.
  • AI apps (OAuth): read scope.

QUERY PARAMETERS

  • days integer default 90

RETURNS

GET/v1/disputes/summary
curl https://api.nochurn.sh/v1/disputes/summary \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/disputes/summary", {
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const disputesSummary = await res.json();
import requests

res = requests.get(
    "https://api.nochurn.sh/v1/disputes/summary",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
disputes_summary = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/summary")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
disputes_summary = JSON.parse(res.body)
RESPONSE 200
{
  "object": "disputes_summary",
  "livemode": false,
  "days": 90,
  "open": 1,
  "due_within_72h": 0,
  "next_due_at": "2026-11-09T10:00:00Z",
  "drafts_ready": 1,
  "open_amount": [
    {
      "currency": "eur",
      "amount_cents": 4900
    }
  ],
  "won": 0,
  "lost": 0,
  "decided": 0,
  "win_rate": null,
  "win_score_accuracy": {
    "decided": 0,
    "right": 0,
    "rate": null
  },
  "won_amount": [],
  "fraud_warnings_open": 0,
  "fraud_warnings_refunded": 0
}

Include, exclude, reorder or add evidence

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

  • items array of objects
    Show child parametersHide child parameters
  • add object
    Show child parametersHide child parameters

RETURNS

PATCH/v1/disputes/{id}/evidence
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence \
  -X PATCH \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "id": "dev_sfrkQKYjndBpn7sB",
        "included": false
      }
    ],
    "add": {
      "title": "Terms accepted at signup",
      "content": "v3, 2026-01-04"
    }
  }'
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence", {
  method: "PATCH",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "items": [
      {
        "id": "dev_sfrkQKYjndBpn7sB",
        "included": false
      }
    ],
    "add": {
      "title": "Terms accepted at signup",
      "content": "v3, 2026-01-04"
    }
  }),
});
const dispute = await res.json();
import requests

res = requests.patch(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "items": [
        {
          "id": "dev_sfrkQKYjndBpn7sB",
          "included": False
        }
      ],
      "add": {
        "title": "Terms accepted at signup",
        "content": "v3, 2026-01-04"
      }
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "items" => [
    {
      "id" => "dev_sfrkQKYjndBpn7sB",
      "included" => false
    }
  ],
  "add" => {
    "title" => "Terms accepted at signup",
    "content" => "v3, 2026-01-04"
  }
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_Rj5wjxQEaNy9JPW1",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_QKuRXU8hJQqAHwRc",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_iHbcRo3tbNDxfwMv",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 3,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_sfrkQKYjndBpn7sB",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": false,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_DV9iYbojhjifRhC7",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    },
    {
      "id": "dev_qdxtS4tUW5xDEPZ4",
      "object": "dispute_evidence_item",
      "kind": "other",
      "title": "Terms accepted at signup",
      "content": "v3, 2026-01-04",
      "source_type": "manual",
      "source_id": "54c0dcfe-ff8a-42ce-a4bb-720a027198e9",
      "occurred_at": null,
      "included": true,
      "position": 3,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_E1iWTCka5FaM988J",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_sfrkQKYjndBpn7sB", "dev_DV9iYbojhjifRhC7"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": "contest",
    "reason": "1 piece of evidence from NoChurn's records.",
    "evidence_count": 1,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Attach a file as evidence (admin+)

PDF, JPEG or PNG, 5 MB at most per file; the type is read from the file's bytes, not its name. For a Stripe dispute, one file per evidence field (the field of its kind, then uncategorized_file) and 4.5 MB of included files in all. Kept by NoChurn until the reply is sent, then given to the provider (Stripe Files API, Razorpay documents); a provider that takes no files (Braintree) gets the file named in the reply. Refused once the reply is sent or for a dispute the provider handles.

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERSmultipart/form-data

  • file string file REQUIRED

    PDF, JPEG or PNG, at most 5 MB.

  • kind enum default "other"

    What the file proves; picks its Stripe evidence field.

    • communication
    • policy
    • usage
    • reminder
    • cancel_history
    • refund_history
    • receipt
    • other
  • title string 200 characters at most

    Defaults to the file name.

RETURNS

ERRORS

POST/v1/disputes/{id}/evidence_files
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files \
  -H "Authorization: Bearer nc_test_…" \
  -F file=@evidence.pdf
import { openAsBlob } from "node:fs";

const form = new FormData();
form.append("file", await openAsBlob("evidence.pdf"), "evidence.pdf");

const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
  },
  body: form,
});
const dispute = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    files={"file": open("evidence.pdf", "rb")},
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req.set_form([["file", File.open("evidence.pdf")]], "multipart/form-data")

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 201
{
  "id": "dsp_Na6rvG7ku8MtRaDv",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_mLiVFHx89vq9XnXZ",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_64GTYRa6AoYRm1H7",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 3,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_RfiKG9mqpf14mwbe",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_AkhDCxNfD6Kt6Gd9",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    },
    {
      "id": "dev_jTobuAp3akY663Wa",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Terms accepted at signup",
      "content": "File attached by the merchant: terms.pdf (PDF, 51 Bytes).",
      "source_type": "file",
      "source_id": "9df4060a-9560-4835-9636-af43eaf834e7",
      "occurred_at": "2026-11-04T10:00:00Z",
      "included": true,
      "position": 3,
      "file": {
        "filename": "terms.pdf",
        "content_type": "application/pdf",
        "byte_size": 51,
        "sent_to_provider": false
      }
    }
  ],
  "draft": {
    "id": "ddr_VxjQntJkeR1w9xhb",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_RfiKG9mqpf14mwbe", "dev_AkhDCxNfD6Kt6Gd9"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": "contest",
    "reason": "1 piece of evidence from NoChurn's records.",
    "evidence_count": 1,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Remove an attached file before sending (admin+)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED
  • file_id string REQUIRED

    The evidence item (dev_…) that holds the file.

RETURNS

ERRORS

DELETE/v1/disputes/{id}/evidence_files/{file_id}
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files/{file_id} \
  -X DELETE \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files/{file_id}", {
  method: "DELETE",
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const dispute = await res.json();
import requests

res = requests.delete(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files/{file_id}",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/evidence_files/{file_id}")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_YLweuRk1thhtFAYb",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_mCEQdXjjESrDrJDG",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_FtWgoBbNnircx8KD",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_4wYdXTX8SmoX9sxY",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_e4s6jyuCNDEvXSnz",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_hrCWnUdvgHduoCqh",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_4wYdXTX8SmoX9sxY", "dev_e4s6jyuCNDEvXSnz"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": null,
    "reason": "No evidence from a record. Set the cost of contesting in Chargebacks › Settings to compare it with the amount.",
    "evidence_count": 0,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Draft the reply again (AI, from the included evidence)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

RETURNS

POST/v1/disputes/{id}/draft
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft \
  -X POST \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const dispute = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 201
{
  "id": "dsp_HtxpkYjWAKTfm2Up",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_J9fwTTz5CCnMQ9aH",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_tTkMw8fApKsvgKJS",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_btvZe1j2d5g3NpzY",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_QTqAuzsLxD1tJMvd",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_TZhtPxA84uU2PQ3i",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_btvZe1j2d5g3NpzY", "dev_QTqAuzsLxD1tJMvd"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": null,
    "reason": "No evidence from a record. Set the cost of contesting in Chargebacks › Settings to compare it with the amount.",
    "evidence_count": 0,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Edit or approve the reply

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

RETURNS

PATCH/v1/disputes/{id}/draft
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft \
  -X PATCH \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "We contest: the customer never asked to cancel.",
    "status": "approved"
  }'
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft", {
  method: "PATCH",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "text": "We contest: the customer never asked to cancel.",
    "status": "approved"
  }),
});
const dispute = await res.json();
import requests

res = requests.patch(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "text": "We contest: the customer never asked to cancel.",
      "status": "approved"
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/draft")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "text" => "We contest: the customer never asked to cancel.",
  "status" => "approved"
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_qsKJ2P9jLqWDH6Ef",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_ZZJu5H56QFUahsJ1",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_ugS68ZNSH6gn8HwH",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "approved",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_SUnk9iZDSZbDHAQh",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_tiRpmG1reTLXsQag",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_iN69iJm2qEJVTAcB",
    "object": "dispute_draft",
    "text": "We contest: the customer never asked to cancel.",
    "cited_item_ids": ["dev_SUnk9iZDSZbDHAQh", "dev_tiRpmG1reTLXsQag"],
    "model": "template",
    "status": "approved",
    "edited_by": "key_V7qug9n5dKhA1X9u",
    "edited_at": "2026-11-04T10:00:00Z",
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": null,
    "reason": "No evidence from a record. Set the cost of contesting in Chargebacks › Settings to compare it with the amount.",
    "evidence_count": 0,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": null,
    "expected_gain_cents": null
  }
}

Send the reply to the provider (admin+, final)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

RETURNS

ERRORS

POST/v1/disputes/{id}/submit
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/submit \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "confirm": true
  }'
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/submit", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "confirm": true
  }),
});
const dispute = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/submit",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "confirm": True
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/submit")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "confirm" => true
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_QzSx4QbyyTkisnRu",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_DZQ97JHJBDsX7jrm",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_LLSMeaxBDkN75sB1",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "under_review",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": "2026-11-04T10:00:00Z",
  "submitted_by": "key_Gb3rYm1g8cgZ6EtX",
  "provider_submitted": false,
  "read_only": true,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "sent",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_886VuUUzD8FfhMYo",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_vo1o3ad11iPAmsYJ",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_Ryx7fL7364Rn2p6h",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_886VuUUzD8FfhMYo", "dev_vo1o3ad11iPAmsYJ"],
    "model": "template",
    "status": "sent",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": null
}

Accept the dispute (admin+, final)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

RETURNS

ERRORS

POST/v1/disputes/{id}/accept
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/accept \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "confirm": true
  }'
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/accept", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "confirm": true
  }),
});
const dispute = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/accept",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "confirm": True
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/accept")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "confirm" => true
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_8BSADXr3AJYpLChN",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_6SJXLf7oAZC72G86",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_AQJjCENwQCV4zoni",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "accepted",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": "2026-11-04T10:00:00Z",
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": true,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "draft",
  "win_score": null,
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_zeBXp3xgZYonNaAr",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_cCLChQGq6RWCBhqN",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_qEE9rTYVtmPtMSid",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_zeBXp3xgZYonNaAr", "dev_cCLChQGq6RWCBhqN"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": null
}

Set the chance of winning yourself, or give it back to the AI (admin+)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

  • score integer | null 0 to 100 REQUIRED

RETURNS

ERRORS

PATCH/v1/disputes/{id}/win_score
curl https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/win_score \
  -X PATCH \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "score": 65
  }'
const res = await fetch("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/win_score", {
  method: "PATCH",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "score": 65
  }),
});
const dispute = await res.json();
import requests

res = requests.patch(
    "https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/win_score",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "score": 65
    },
)
dispute = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/disputes/dsp_2F9vssKp8BhfWwe9/win_score")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "score" => 65
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
dispute = JSON.parse(res.body)
RESPONSE 200
{
  "id": "dsp_LAPfbdgzPUevBEks",
  "object": "dispute",
  "livemode": false,
  "provider": "stripe",
  "billing_connection": "scn_ZhJbRPTgnePzxjVs",
  "external_id": "dp_1",
  "charge": "ch_1",
  "customer": "cst_jG4aKZ2xDye6LEtD",
  "customer_name": "Lena",
  "customer_email": "customer1@acme-corp.dev",
  "customer_plan": "Pro",
  "amount_cents": 4900,
  "currency": "eur",
  "reason": "subscription_canceled",
  "status": "needs_response",
  "evidence_due_by": "2026-11-09T10:00:00Z",
  "opened_at": "2026-11-04T10:00:00Z",
  "outcome_at": null,
  "submitted_at": null,
  "submitted_by": null,
  "provider_submitted": false,
  "read_only": false,
  "capability": "evidence_api",
  "evidence_count": 2,
  "draft_status": "draft",
  "win_score": {
    "score": 65,
    "source": "manual",
    "confidence": null,
    "factors": [],
    "evidence_count": null,
    "model": null,
    "set_by": "key_KtYf839pxVaXiWsn",
    "computed_at": "2026-11-04T10:00:00Z"
  },
  "created_at": "2026-11-04T10:00:00Z",
  "evidence": [
    {
      "id": "dev_JdC44XCLiiz2kLxu",
      "object": "dispute_evidence_item",
      "kind": "cancel_history",
      "title": "No cancellation request",
      "content": "The customer never opened the cancellation flow before the dispute.",
      "source_type": "nochurn",
      "source_id": "cancel_history",
      "occurred_at": null,
      "included": true,
      "position": 1,
      "file": null
    },
    {
      "id": "dev_MPZaQk8n7KM3cABs",
      "object": "dispute_evidence_item",
      "kind": "policy",
      "title": "Cancellation policy",
      "content": "Cancellation is available at any time in the app.",
      "source_type": "nochurn",
      "source_id": "policy",
      "occurred_at": null,
      "included": true,
      "position": 2,
      "file": null
    }
  ],
  "draft": {
    "id": "ddr_V9zGUkjGoVRGn4zG",
    "object": "dispute_draft",
    "text": "We contest this subscription canceled dispute.\n\nEvidence:\n- No cancellation request: The customer never opened the cancellation flow before the dispute.\n- Cancellation policy: Cancellation is available at any time in the app.",
    "cited_item_ids": ["dev_JdC44XCLiiz2kLxu", "dev_MPZaQk8n7KM3cABs"],
    "model": "template",
    "status": "draft",
    "edited_by": null,
    "edited_at": null,
    "created_at": "2026-11-04T10:00:00Z"
  },
  "charge_details": {
    "paid_at": "2026-11-03T10:00:00Z",
    "plan": "Pro",
    "invoice": null,
    "period_end": null
  },
  "recommendation": {
    "suggestion": null,
    "reason": "No evidence from a record. Set the cost of contesting in Chargebacks › Settings to compare it with the amount.",
    "evidence_count": 0,
    "amount_cents": 4900,
    "contest_cost_cents": null,
    "currency": "eur",
    "win_score": 65,
    "expected_gain_cents": null
  }
}

Early fraud warnings

  • Secret key (nc_test_… or nc_live_…). Restricted keys need read access.
  • AI apps (OAuth): read scope.

QUERY PARAMETERS

RETURNS

GET/v1/fraud_warnings
curl https://api.nochurn.sh/v1/fraud_warnings \
  -H "Authorization: Bearer nc_test_…"
const res = await fetch("https://api.nochurn.sh/v1/fraud_warnings", {
  headers: {
    Authorization: "Bearer nc_test_…",
  },
});
const page = await res.json();
import requests

res = requests.get(
    "https://api.nochurn.sh/v1/fraud_warnings",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
)
page = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/fraud_warnings")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
page = JSON.parse(res.body)
RESPONSE 200
{
  "object": "list",
  "data": [
    {
      "id": "efw_UV9yBsfrkR2nKpAR",
      "object": "fraud_warning",
      "livemode": false,
      "provider": "stripe",
      "external_id": "issfr_1",
      "charge": "ch_9",
      "customer": null,
      "customer_name": null,
      "customer_email": null,
      "customer_plan": null,
      "amount_cents": null,
      "currency": null,
      "fraud_type": "misc",
      "actionable": true,
      "action": "none",
      "acted_by": null,
      "acted_at": null,
      "note": null,
      "created_at": "2026-11-04T10:00:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Refund before the dispute (admin+, final)

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

RETURNS

POST/v1/fraud_warnings/{id}/refund
curl https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/refund \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "confirm": true
  }'
const res = await fetch("https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/refund", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "confirm": true
  }),
});
const fraudWarning = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/refund",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "confirm": True
    },
)
fraud_warning = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/refund")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "confirm" => true
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
fraud_warning = JSON.parse(res.body)
RESPONSE 200
{
  "id": "efw_K5887AXzbU8YgLAM",
  "object": "fraud_warning",
  "livemode": false,
  "provider": "stripe",
  "external_id": "issfr_1",
  "charge": "ch_9",
  "customer": null,
  "customer_name": null,
  "customer_email": null,
  "customer_plan": null,
  "amount_cents": null,
  "currency": null,
  "fraud_type": "misc",
  "actionable": true,
  "action": "refunded",
  "acted_by": "key_zA9EmYgpvf29Cd1D",
  "acted_at": "2026-11-04T10:00:00Z",
  "note": null,
  "created_at": "2026-11-04T10:00:00Z"
}

Keep the payment

  • Secret key (nc_test_… or nc_live_…). Restricted keys need write access.
  • AI apps (OAuth): not available.

PATH PARAMETERS

  • id string REQUIRED

BODY PARAMETERS

RETURNS

POST/v1/fraud_warnings/{id}/dismiss
curl https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/dismiss \
  -H "Authorization: Bearer nc_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "Known customer"
  }'
const res = await fetch("https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/dismiss", {
  method: "POST",
  headers: {
    Authorization: "Bearer nc_test_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "note": "Known customer"
  }),
});
const fraudWarning = await res.json();
import requests

res = requests.post(
    "https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/dismiss",
    headers={
        "Authorization": "Bearer nc_test_…",
    },
    json={
      "note": "Known customer"
    },
)
fraud_warning = res.json()
require "net/http"
require "json"

uri = URI("https://api.nochurn.sh/v1/fraud_warnings/efw_UV9yBsfrkR2nKpAR/dismiss")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
  "note" => "Known customer"
}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
fraud_warning = JSON.parse(res.body)
RESPONSE 200
{
  "id": "efw_gw2bmQewwphGBtAv",
  "object": "fraud_warning",
  "livemode": false,
  "provider": "stripe",
  "external_id": "issfr_1",
  "charge": "ch_9",
  "customer": null,
  "customer_name": null,
  "customer_email": null,
  "customer_plan": null,
  "amount_cents": null,
  "currency": null,
  "fraud_type": "misc",
  "actionable": true,
  "action": "dismissed",
  "acted_by": "key_TaFFSqDwmBtFwbL3",
  "acted_at": "2026-11-04T10:00:00Z",
  "note": "Known customer",
  "created_at": "2026-11-04T10:00:00Z"
}