Chargeback Agent API
Upload dispute documents and receive a recommendation, recommended actions, and a formal response letter. Requests authenticate by secret key.
Agent Lifecycle
A case moves through these steps:
-
Initialize agent with a chargeback case (
POST) -
Attach documents to the case (
POST,PUT) - Agent recommendation (
GET) - Generate response letter (
POST) - Read response letter (
GET)
Repeat the attach and recommendation steps until the case is ready. Each
recommendation reports its confidence and suggests further
evidence to attach.
When the recommendation is ready, download the PDF in two steps:
- Request download (
GET) - Download document (
GET)
Initialize Chargeback Case
Initialize an agent session with chargeback case details. The response
carries the case id for later requests. No field is required,
and a complete request body gives the best results.
A blank field is treated as omitted. null and an empty string
mean the same thing. On initialize the field stays unset, and on update the field is cleared.
Request
POST /chargeback
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
{
data: {
agent: Boolean | Object,
amount: Number,
cardNetwork: String,
cardholderName: String,
currency: String,
disputeDate: String,
dueDate: String,
maskedCardNumber: String,
merchantIdentifier: String,
merchantName: String,
merchantUrl: String,
reasonCode: String,
reasonDescription: String,
referenceNumber: String,
transactionDate: String
}
}
| Field | Type | Description |
|---|---|---|
agent |
Boolean or Object |
Chargeback Agent behavior. true follows the
organization's settings, false disables agent research,
and an object sets each behavior. Default true. Accepted
on the request and never returned. See agent settings
|
amount |
Number | Disputed amount in major units, such as dollars |
cardNetwork |
String | Card network of the disputed transaction, such as "visa". Scopes reasonCode matching when maskedCardNumber lacks the leading digits |
cardholderName |
String | Name of the disputing cardholder |
currency |
String (ISO 4217) | Transaction currency. Default "USD" |
disputeDate |
Date (ISO 8601) | Date the dispute was raised |
dueDate |
Date (ISO 8601) | Deadline for the merchant response |
maskedCardNumber |
String | Masked card number with its leading digits, such as "424242******4242". The leading digits scope reasonCode matching. A number
without leading digits, such as "******4242", uses cardNetwork instead |
merchantIdentifier |
String | Organization's identifier for the merchant defending the case |
merchantName |
String | Merchant trading name |
merchantUrl |
String (URL) | Merchant public website. The agent reads the business description and dispute policies on the site for the recommendation. The address is normalized, so the returned value can differ from the value sent |
reasonCode |
String |
Card network reason code. Matching accepts the code formats processors
export when the card network is known from maskedCardNumber or cardNetwork. Without a card network, only a code
cataloged exactly as written resolves
|
reasonDescription |
String | Dispute description in the caller's wording. Confirms which dispute a reasonCode names when the code uses another network's scheme. Never overrides reasonCode |
referenceNumber |
String | Dispute reference number from the processor or card network |
transactionDate |
Date (ISO 8601) | Date of the disputed transaction |
Response
The response returns the submitted details with the case id and
status. The reason code defenseRequirements are
available immediately. Each requirement changes to satisfied: true as evidence arrives. Meet as many requirements as possible to maximize
success.
evidenceSuggested and evidenceProvided describe
the evidence types that meet defense requirements, in merchant-friendly
terms. recommendedActions lists more specific actions.
{
data: {
amount: Number,
cardNetwork: String,
cardholderName: String,
currency: String,
defenseRequirements: [{ requirement: String, satisfied: Boolean }],
disputeDate: String,
dueDate: String,
evidenceProvided: [String],
evidenceSuggested: [String],
id: String,
maskedCardNumber: String,
merchantIdentifier: String,
merchantName: String,
merchantUrl: String,
reasonCode: String,
reasonDescription: String,
referenceNumber: String,
status: "pending",
transactionDate: String
}
}
| Field | Type | Description |
|---|---|---|
defenseRequirements |
Array of Objects |
Proof the reason code requires of the defense. Every item is satisfied: false until the agent assesses attached documents. Empty when the case has
no reasonCode or an unrecognized one
|
evidenceProvided |
Array of Strings | Evidence categories with at least one satisfied requirement. Empty at initialization, until a document is attached or the agent retrieves evidence |
evidenceSuggested |
Array of Strings |
Evidence categories still to collect, highest impact first. Every
category a merchant can supply when reasonCode is absent
or unrecognized
|
id |
String (uuid) | Identifier for the agent session |
status |
String (enum) | pending until a document is attached |
Agent Settings
The agent field controls agent behavior for the case. The field
is accepted on the request and never returned.
| Value | Description |
|---|---|
Omitted or true |
Every setting keeps its default |
false |
Every setting is false |
| Object | Named settings take the posted value, and the rest keep their defaults |
Agent settings object
Settings are fixed when the case is created. An agent field
posted to update answers 400 Bad Request.
Defaults vary by organization. Contact Findustry AI to discuss customizations.
{
data: {
agent: {
researchTransactionDetails: Boolean,
submitDisputeToProcessor: Boolean,
useMerchantMemories: Boolean,
writeResponseLetter: Boolean
}
}
}
| Setting | Type | Description |
|---|---|---|
researchTransactionDetails |
Boolean | Agent research of transaction details beyond the case and its attached documents |
submitDisputeToProcessor |
Boolean |
Agent filing of the response with the issuer or processor. When
false, the agent provides the response for the
organization to file
|
useMerchantMemories |
Boolean | Agent use of past research and interactions for the case. By default, the agent remembers which evidence types a merchant can or cannot provide |
writeResponseLetter |
Boolean |
Agent writing of a response letter for the
case. When false, POST /chargeback/:id/letter answers 400 Bad Request
|
Evidence Categories
evidenceProvided and evidenceSuggested use the
lowercase values below.
| Value | Description |
|---|---|
cardholder communication |
Correspondence with the cardholder, such as email conversations or post-payment agreements |
cardholder transaction history |
Cardholder's prior undisputed transactions with the merchant |
delivery confirmation |
Proof the order reached the cardholder, such as signed delivery confirmation or courier tracking |
evidence of product quality |
Evidence the goods were as described, such as condition photographs or a certificate of authenticity |
order confirmation |
Records of the order as placed, such as the confirmation email sent to the cardholder |
proof of cardholder non-contact / non-return |
Proof the cardholder neither contacted the merchant nor returned the merchandise |
proof of digital goods usage |
Proof digital content was delivered, such as purchase and download timestamps or access logs |
proof of services provided |
Proof services were provided and used, such as an invoice or a service confirmation |
recurring billing records |
Subscription billing and cancellation records, such as the billing notice sent to the cardholder |
refund and return policies |
Merchant's published policies and their acceptance, such as a checkout acceptance screenshot |
refund receipt |
Refund and credit records, such as proof a credit was already issued |
transaction authorization |
Payment platform's record of the transaction and its authorization, such as the sales slip, AVS and CVV results, or device fingerprints |
Update Case Details
Post only the fields to change. Fields omitted from data stay
unchanged. The request accepts the same fields as initialize, except agent, which answers 400 Bad Request.
A blank field clears the value on the case. null and an empty
string mean the same thing. Every field can be cleared except referenceNumber. Clearing referenceNumber answers 400 Bad Request.
Request
POST /chargeback/:id
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
{
data: {
dueDate: String,
merchantUrl: String
}
}
Response
The response returns the updated case in the same shape as initialize.
Delete Case
Delete a case and its attached documents. Deleted cases and their documents cannot be retrieved.
Request
DELETE /chargeback/:id
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Response
{
data: {
id: String,
status: "deleted"
}
}
Attach Documents to Case
Post the uploadFilenames, then send each file's contents to its
signed putUrl, as in document upload. The next recommendation assesses each
attached document.
Attach documents to cases initialized with POST /chargeback. A session initialized with direct upload
takes its documents at initialization, and this endpoint answers 400 Bad Request for it.
Request
POST /chargeback/:id/upload
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
{
data: {
uploadFilenames: [String]
}
}
Response
{
data: {
id: String,
putUrls: [
{
evidenceId: String,
putUrl: String,
uploadFilename: String
}
]
}
}
Each signed putUrl is valid for five minutes. Each evidenceId identifies the attached document for evidence deletion.
Delete Evidence from Case
Delete a single attached document by its evidenceId. The case
and its remaining documents are unchanged. Deleted documents cannot be
retrieved.
The agent reassesses the case about thirty seconds after the last deletion,
so a burst of deletions is assessed once. The recommendation shows status: "processing" during reassessment and completes
with the remaining evidence.
Deleting evidence also retires any response letter already written, because
the letter argued from the deleted document. GET /chargeback/:id/letter answers 404 Not Found until the next response letter request, which rewrites the letter from the remaining evidence. To replace
a letter and keep the evidence, discard the letter instead.
Request
DELETE /chargeback/:id/evidence/:evidenceId
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
| Parameter | Type | Description |
|---|---|---|
evidenceId |
String (uuid) | Identifier for the attached document, returned by attach |
id |
String (uuid) | Identifier for the agent session |
Response
{
data: {
id: String,
status: "deleted"
}
}
| Field | Type | Description |
|---|---|---|
id |
String (uuid) | Identifier for the deleted evidence |
status |
String (enum) | Value deleted |
Agent Recommendation
After each document upload, the agent assesses the case and provides a
recommendation and recommended actions. The response shows status: "processing" while the agent works. Assessment takes several minutes.
Every status returns the submitted case fields and the current status. On completion, the response adds the recommendation fields.
Request
GET /chargeback/:id
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Response
Processing
{
data: {
amount: Number,
cardNetwork: String,
currency: String,
// ...the case fields as submitted...
defenseRequirements: [{ requirement: String, satisfied: Boolean }],
evidenceProvided: [String],
evidenceSuggested: [String],
id: String,
status: "processing"
}
}
Complete
{
data: {
amount: Number,
cardNetwork: String,
currency: String,
// ...the case fields as submitted...
confidence: Number,
defenseRequirements: [{ requirement: String, satisfied: Boolean }],
evidenceProvided: [String],
evidenceSuggested: [String],
id: String,
merchantAttachments: [{ evidenceId: String, uploadFilename: String }],
merchantIdentifier: String,
priority: String,
recommendation: String,
recommendedActions: [String],
referenceNumber: String,
status: String
}
}
| Field | Type | Description |
|---|---|---|
confidence |
Number |
Confidence in the recommendation, 0 to 100
|
defenseRequirements |
Array of Objects |
requirement and its satisfied flag, set by
the assessment from the attached documents. The set stays stable for
the life of the case. Evidence matching no known requirement is
appended
|
evidenceProvided |
Array of Strings | Satisfied evidence categories |
evidenceSuggested |
Array of Strings | Unsatisfied evidence categories that would strengthen the defense. Updated with each attachment or deletion |
id |
String (uuid) | Identifier for the agent session |
merchantAttachments |
Array of Objects |
Current case documents, after deletions. Each object carries the evidenceId for evidence deletion and the uploadFilename
|
merchantIdentifier |
String |
merchantIdentifier posted on the case. Absent when the
case has none
|
priority |
String (enum) | normal, high |
recommendation |
String |
respond, accept, hold. accept means the merchant accepts the chargeback, and the agent writes no
response letter
|
recommendedActions |
Array of Strings | Actions that can strengthen the merchant defense |
referenceNumber |
String | Dispute reference number from the processor or card network |
status |
String (enum) |
pending, queued, processing, complete, error
|
When processing fails, the response carries a message in place
of the recommendation.
{
data: {
id: String,
message: String,
status: "error"
}
}
Generate Response Letter
When the recommendation is satisfactory, request a formal response letter.
The response shows status: "processing" while the agent works.
Writing takes several minutes. Read the letter
until it is ready, or register a web hook.
The agent writes a letter once, and only on request. A repeat request returns the existing letter. To replace a letter, discard it first.
This request takes no body. A request with a body answers 400 Bad Request.
Request
POST /chargeback/:id/letter
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Response
First request
{
data: {
id: String,
status: "processing"
}
}
Requested again, letter ready
{
data: {
id: String,
responseLetter: String,
status: "complete"
}
}
Read Response Letter
Poll the requested letter until it is ready. The request answers 404 Not Found when the letter was never requested, or was retired
by discarding it or by deleting evidence.
Request
GET /chargeback/:id/letter
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Response
Processing
{
data: {
id: String,
status: "processing"
}
}
Complete
{
data: {
id: String,
responseLetter: String,
status: "complete"
}
}
| Field | Type | Description |
|---|---|---|
id |
String (uuid) | Identifier for the agent session |
responseLetter |
String (markdown) | Complete rebuttal letter for the acquirer and card networks |
Not requested
HTTP 404
{
errors: [
{
status: 404,
title: String,
detail: String
}
]
}
Discard Response Letter
Discard the response letter for a case, then request a letter to write a new one. The attached documents stay attached to the case.
Discarding a letter in progress abandons it, and the agent delivers no
letter from that work. A case with no letter to discard answers 404 Not Found, as reading the letter does. This request takes
no body. A request with a body answers 400 Bad Request.
Request
DELETE /chargeback/:id/letter
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Response
{
data: {
id: String,
status: "deleted"
}
}
Direct Upload and Download
Initialize with Direct Upload
Direct upload reads chargeback details from an existing file. Chargeback Agent requires configuration to recognize upload formats before use. Contact support@findustryai.com to configure formats.
Details
Initialize an agent session by posting the uploadFilename of
the document to upload. Filenames may be repeated across sessions. The
response provides the signed putUrl for the file contents.
A direct-upload session carries one document. To assess several documents together, initialize a case with POST /chargeback and attach each document to it.
Request
POST /chargeback/upload
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
{
data: {
uploadFilename: String
}
}
| Field | Type | Required | Description |
|---|---|---|---|
uploadFilename |
String (filename) | Yes | Name of the file to upload. A filename, never a path |
Response
{
data: {
id: String,
putUrls: [
{
evidenceId: String,
putUrl: String,
uploadFilename: String
}
]
}
}
| Field | Type | Description |
|---|---|---|
id |
String (uuid) | Identifier for the agent session |
putUrls |
Array of one Object |
uploadFilename, its signed putUrl for the
document PUT, and the evidenceId for evidence deletion. The putUrl is valid for five minutes
|
Document Upload
After initialization, send the file's contents to its signed putUrl. The URL is valid for five minutes.
PUT ${putUrl}
Content-Type: ${contentType}
Example using curl:
curl -X PUT -T file.pdf
"https://bucket.s3.amazonaws.com/file.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=300&X-Amz-Signature=..."
Document Export
Document export assembles case files in custom formats, such as PDF or XLSX. Chargeback Agent requires configured export formats before use. Contact support@findustryai.com to configure formats.
Details
The agent produces an export in the requested format. The response shows status: "processing" while the agent works. Export takes several minutes. When the download
is ready, the response returns a getUrl.
Request
GET /chargeback/:id/download
Authorization: sk_findustryai_kkkkkkkkkkkk_nnnnn
Multiple Formats
When several formats are configured, the format query
parameter selects one. Without format, the response returns
the default format.
Response
Processing
{
data: {
id: String,
status: "processing"
}
}
Complete
{
data: {
id: String,
getUrl: String
}
}
| Field | Type | Description |
|---|---|---|
getUrl |
String (URL) | Signed URL for the document |
id |
String (uuid) | Identifier for the agent session |
Document Download
The download request returns a signed getUrl. The URL is
valid for five minutes.
Example using curl:
curl -L -o file.pdf
"https://bucket.s3.amazonaws.com/file.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=300&X-Amz-Signature=..."
Web Hooks
Register a web hook in place of polling the agent status. The event body
carries the same data as the HTTP response, plus metadata. Security headers authenticate each delivery.
Event Metadata
{
metadata: {
attempt: Number,
event: String,
id: String,
timestamp: Number,
type: "webhook",
webhook: String
},
data: {
// …
}
}
| Field | Type | Description |
|---|---|---|
attempt |
Number (integer) | Delivery attempt count, starting at 1 |
event |
String |
chargeback:copilot for the agent result,
chargeback:letter for the response letter
|
id |
String (uuid) | Event identifier, unchanged across attempts. Idempotency token |
timestamp |
Number (milliseconds) | Attempt time. Changes with each attempt |
type |
String | Value webhook |
webhook |
String (uuid) | Endpoint receiving delivery |
Acknowledgment
| Code | Description | Result | Retried |
|---|---|---|---|
2XX |
Success | Delivered | No |
401 |
Unauthorized | Failed authentication | No |
429 |
Too many requests | Rate limited | Yes, with backoff |
5XX |
Server error | Receiver failed | Yes, with backoff |
504 |
Gateway Timeout | No response after 15 seconds, or unreachable host |
Yes, with backoff |
* |
Unknown error | Client error, including 3XX |
No |
Undeliverable Messages
Findustry AI retries an undeliverable message for up to one hour. When a message still fails after one hour, Findustry AI contacts the organization to discuss delivery rates.
Authentication
Each web hook delivery carries an HMAC signature in the X-Webhook-Signature header. See Web Hooks authentication.