Generate evidence in seconds
Use Evidence-as-a-Service to turn dispute data into a bank-ready PDF, then download it when the evidence.ready webhook fires.
Evidence-as-a-Service (EaaS) turns dispute data into a polished, bank-ready PDF evidence package in about 30 seconds (up to ~3 minutes). This recipe is a full, copy-paste-runnable flow: call the Generate Evidence API, wait for the evidence.ready webhook, then fetch the PDF link.
EaaS is a platform-level integration. Platforms call it on behalf of their merchants. Merchants never call it directly. See What is EaaS?.
Before you start
- EaaS must be enabled on your Connect account by your Chargeflow account manager. Without it, every EaaS call returns
403_eaas_not_enabled. See What is EaaS?. - Get your platform
API Access Key. Every request sends it in thex-api-keyheader. See Authentication. - Subscribe to the
evidence.readyandevidence.errorwebhooks in the Connect Developer Hub. See How It Works.
All requests go to https://api.chargeflow.io under the /public/2025-04-01/ path.
Steps
Call the Generate Evidence API
POST /public/2025-04-01/evidence accepts either an existing Chargeflow dispute_id or a full inline dispute object. You do not need to create the dispute separately first. Provide exactly one of the two.
The dispute must be in needs_response status, otherwise the call returns 422_dispute_invalid_state.
Option A: reference an existing dispute:
curl -X POST https://api.chargeflow.io/public/2025-04-01/evidence \
-H "x-api-key: YOUR_PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "66e6ea9ecd94925a9f8060d9",
"dispute": {
"dispute_id": "66e6ea9ecd94925a9f8060d9"
}
}'Option B: submit the dispute data inline:
curl -X POST https://api.chargeflow.io/public/2025-04-01/evidence \
-H "x-api-key: YOUR_PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "66e6ea9ecd94925a9f8060d9",
"dispute": {
"dispute_data": {
"source_id": "du_123456789",
"created_at": "2024-02-10T12:00:00Z",
"reason": "fraud",
"due_by": "2024-02-20T12:00:00Z",
"amount": 150.00,
"currency": "USD",
"status": "needs_response",
"transaction": {
"source_id": "tx_1234567890",
"created_at": "2024-02-08T10:00:00Z",
"type": "paid",
"amount": 150.00,
"currency": "USD"
}
}
}
}'The API responds immediately with in_progress. Generation is asynchronous, so the PDF is not in this response.
{
"id": "ev_abc123456789",
"account_id": "acct_9876543210",
"ext_account_id": "ext_acct_54321",
"dispute": "dp_1122334455",
"created_at": "2025-07-29T14:35:00Z",
"status": "in_progress",
"file_url": null,
"file_version": 1
}Note
Store the id as your persistent reference to this evidence package. The id is permanent; the file_url is temporary and expires 7 days after it is issued. See Privacy & Security.
Wait for the evidence.ready webhook
Do not poll in a tight loop. Chargeflow pushes the result to your webhook endpoint when the PDF is ready (evidence.ready) or if generation fails (evidence.error). Generation typically completes in about 30 seconds, with a maximum of around 3 minutes.
evidence.ready payload:
{
"event": {
"id": "evt_XXXXXXXXXXXXXXXX",
"type": "evidence.ready",
"created_at": "2025-07-29T12:34:56Z"
},
"evidence": {
"id": "ev_abc123456789",
"account_id": "acct_9876543210",
"ext_account_id": "ext_acct_54321",
"dispute": "dp_1122334455",
"created_at": "2025-07-29T14:35:00Z",
"status": "completed",
"file_url": "https://cdn.chargeflow.io/evidence/ev_abc123456789/v2/evidence.pdf",
"file_version": 1
}
}Acknowledge with a 2XX quickly, then download or store the PDF asynchronously.
app.post('/webhook', express.json(), (req, res) => {
const event = req.body;
res.json({ received: true }); // acknowledge first
if (event.event?.type === 'evidence.ready') {
const { id, file_url } = event.evidence;
// Download the PDF and submit it to your PSP
saveEvidencePdf(id, file_url);
}
if (event.event?.type === 'evidence.error') {
// event.error_code and event.error_message explain what failed
console.error(event.error_code, event.error_message);
}
});The evidence.error payload includes error_code and error_message, for example 422_dispute_invalid_state with "Dispute status must be needs_response". See How It Works for both payload shapes.
Fetch the latest evidence link
The download link expires 7 days after it is issued. If you need a fresh link later, read the evidence record by its id with GET /public/2025-04-01/evidence/{evidenceId}.
curl -X GET https://api.chargeflow.io/public/2025-04-01/evidence/ev_abc123456789 \
-H "x-api-key: YOUR_PLATFORM_API_KEY"The response carries the current status, file_url, and file_version:
{
"id": "ev_abc123456789",
"account_id": "acct_9876543210",
"ext_account_id": "ext_acct_54321",
"dispute": "dp_1122334455",
"created_at": "2025-07-29T14:35:00Z",
"status": "completed",
"file_url": "https://cdn.chargeflow.io/evidence/ev_abc123456789/v2/evidence.pdf",
"file_version": 1
}Regenerate when new data arrives (optional)
While the dispute is still in needs_response, you can regenerate the package to fold in new data such as tracking, fulfillment, or added communication logs. Call the same Generate Evidence endpoint again. Each regeneration increments file_version.
curl -X POST https://api.chargeflow.io/public/2025-04-01/evidence \
-H "x-api-key: YOUR_PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "66e6ea9ecd94925a9f8060d9",
"dispute": { "dispute_id": "66e6ea9ecd94925a9f8060d9" }
}'Warning
If a call returns 409_generation_in_progress, do not retry. Wait for the evidence.ready or evidence.error webhook before taking further action.
Report the outcome
When the dispute resolves (won or lost), share the outcome with Chargeflow so the AI keeps improving win rates across your merchants. There is no public endpoint for this yet.
A public Report Outcome endpoint is not available yet. For now, contact your Chargeflow account manager for the preferred method of submitting outcome data for your integration.