For MerchantsAlerts

Deflect chargebacks with alerts

Subscribe to pre-chargeback alerts, receive an alert, refund the transaction, and report the outcome to close the alert.

Pre-chargeback alerts give you a chance to refund a transaction before it becomes a chargeback. (This recipe is about the Alerts product - stopping risky orders before shipment is Prevent.) This recipe is a full, copy-paste-runnable flow for the merchant-managed model: subscribe to alert webhooks, receive an alert, refund the matching transaction in your processor, then report the outcome to Chargeflow so the alert is closed with the issuer.

Before you start

  • Get your API Access Key. Every request sends it in the x-api-key header. See Authentication.
  • All requests go to https://api.chargeflow.io under the /public/2025-04-01/ path.

Note

This recipe covers the merchant-managed model, where you refund and report outcomes yourself. With Chargeflow Alerts (the automated model), Chargeflow matches and refunds automatically, and you do not need to call the outcome endpoint.

Steps

Subscribe to alert events

Register a webhook endpoint for the alert lifecycle events.

Each registration subscribes one endpoint to one event, so register once per event:

Terminal
curl -X POST https://api.chargeflow.io/public/2025-04-01/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "alerts.created", "url": "https://your-server.com/webhooks/alerts-created"}'

curl -X POST https://api.chargeflow.io/public/2025-04-01/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "alerts.updated", "url": "https://your-server.com/webhooks/alerts-updated"}'

See Subscribe to Webhook Events for the full list of events, and Webhooks for signature verification.

Receive the alerts.created webhook

When a card network raises a pre-chargeback alert, Chargeflow posts an alerts.created event to your endpoint. The payload carries the alert ID and the metadata you need to locate the transaction.

Webhook payload
{
  "id": "alert_123456789",
  "account_id": "account_987654321",
  "ext_account_id": "platform_acc_12345",
  "transaction": "txn_abcdef123456",
  "created_at": "2025-07-31T12:34:56Z",
  "status": "alerted",
  "status_date": "2025-07-31T13:00:00Z",
  "statement_descriptor": "My Merchant Store",
  "amount": 12500,
  "currency": "USD",
  "outcome": "pending",
  "type": "fraud_warning",
  "reason": "fraud",
  "network_transaction": {
    "id": "net_txn_78910",
    "created_at": "2025-07-31T12:30:00Z",
    "amount": 12500,
    "currency": "USD",
    "card_brand": "Visa",
    "bin": "411111",
    "last4": "1111",
    "auth_code": "AUTH1234",
    "arn": "ARN56789"
  }
}

Acknowledge with a 2XX quickly, then handle the alert asynchronously.

Node.js
app.post('/webhooks/alerts', express.json(), (req, res) => {
  const alert = req.body;
  res.json({ received: true }); // acknowledge first

  // The alerts.created payload is delivered flat (no envelope): the alert
  // fields are at the top level. Subscribe this endpoint to alerts.created,
  // so every delivery is a new alert. alert.type holds the alert type,
  // for example 'fraud_warning'.
  handleAlert(alert.id);
});

Fetch the full alert (optional)

Some fields, such as the matched transaction reference, may be filled in after ingestion. For the current, complete alert record, read it by ID.

Terminal
curl -X GET https://api.chargeflow.io/public/2025-04-01/alerts/alert_123456789 \
  -H "x-api-key: YOUR_API_KEY"

You can also list alerts with GET /public/2025-04-01/alerts, which supports offset, limit, created_at_min, created_at_max, type, status, reason, and sort query parameters.

Refund the matching transaction

Use the alert metadata to find the charge in your payment processor and refund it. Match on network_transaction.last4, network_transaction.arn, amount, and currency. This step happens in your own processor, not in the Chargeflow API.

Node.js
// Pseudocode against your processor's SDK
const charge = await psp.findCharge({
  last4: alert.network_transaction.last4,
  arn: alert.network_transaction.arn,
  amount: alert.amount,
  currency: alert.currency,
});

await psp.refund(charge.id);

Report the outcome

After processing the alert, report the outcome with POST /public/2025-04-01/alerts/{alertId}/outcome. This is what closes the alert with the issuer. The request body takes a single required outcome field.

Valid outcome values are refunded, previously_refunded, duplicate, decline, and error.

Terminal
curl -X POST https://api.chargeflow.io/public/2025-04-01/alerts/alert_123456789/outcome \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"outcome": "refunded"}'

A successful call returns 202 Accepted.

Warning

In the merchant-managed model, always call the outcome endpoint after handling an alert, even if you could not find the transaction. Without this step, Chargeflow cannot close the alert with the issuer and the chargeback may still be filed.

React to alerts.updated

As the alert moves through its lifecycle, Chargeflow fires alerts.updated. Use it to keep your records in sync. For example, when outcome is prevented, record the successful prevention.

Webhook payload
{
  "id": "alert_123456789",
  "account_id": "account_987654321",
  "status": "prevented",
  "status_date": "2025-07-31T14:00:00Z",
  "amount": 12500,
  "currency": "USD",
  "outcome": "prevented",
  "type": "fraud_warning",
  "reason": "fraud"
}

If outcome is chargebacked, the alert escalated to a chargeback despite mitigation. Watch for dispute.created if you want to begin enrichment. See Automate a chargeback dispute.

Next steps

Was this page helpful?

On this page