Mintcash
ConceptsWebhooks

Payload reference

The JSON shape of every webhook envelope and entity. Use this to write strongly-typed handlers.

Every webhook MintCash sends shares a common envelope. The variable part is data, whose shape is determined by type.

Envelope

FieldTypeNotes
eventIdstring (UUID)Stable across retries of the same event. Use as your dedupe key.
eventstringThe transition: payment.succeeded, subscription.failed, etc.
typestringDetermines the shape of data: payment, subscription, or refund.
apiVersionstringWebhook schema version (2026-05-01).
environmentstringlive or test.
createdAtstring (ISO8601)When the event was emitted.
dataobjectThe entity. Shape depends on type.

Payment payload (type: "payment")

Fires for: payment.created, payment.pending, payment.authorized, payment.succeeded, payment.failed, payment.voided.

{
  "eventId": "01HXX...",
  "event": "payment.succeeded",
  "type": "payment",
  "apiVersion": "2026-05-01",
  "environment": "live",
  "createdAt": "2026-05-22T14:32:08.412Z",
  "data": {
    "id": "pmt_01HXX...",
    "externalId": "order_123",
    "status": "succeeded",
    "amount": 49.99,
    "currency": "USD",
    "providerTransactionId": "provider_txn_abc",
    "failureCode": null,
    "failureMessage": null,
    "amountRefunded": 0,
    "amountRefundable": 49.99,
    "customer": {
      "id": "cust_01HXX...",
      "externalId": "cust_42",
      "email": "buyer@example.com",
      "name": "Jane Doe",
      "phone": "+15551234567"
    },
    "billingAddress": {
      "country": "US",
      "postalCode": "10001",
      "name": "Jane Doe",
      "line1": "1 Madison Ave",
      "line2": null,
      "city": "New York",
      "state": "NY"
    },
    "card": {
      "brand": "mastercard",
      "first6": "555544",
      "last4": "0000",
      "mask": "555544******0000",
      "expMonth": "12",
      "expYear": "2030"
    }
  }
}
type Customer = {
  id: string;
  externalId: string;
  email: string;
  name: string;
  phone: string | null;
};

type Address = {
  country: string;
  postalCode: string;
  name: string | null;
  line1: string | null;
  line2: string | null;
  city: string | null;
  state: string | null;
};

type Card = {
  brand: string;
  first6: string;
  last4: string;
  mask: string;          // already-masked PAN, e.g. 555544******0000
  expMonth: string;
  expYear: string;
};

type PaymentData = {
  id: string;
  externalId: string;
  status:
    | "created"
    | "pending"
    | "authorized"
    | "succeeded"
    | "failed"
    | "voided";
  amount: number;            // major units
  currency: string;
  providerTransactionId: string | null;
  failureCode: string | null;
  failureMessage: string | null;
  amountRefunded: number;
  amountRefundable: number;
  customer: Customer | null;
  billingAddress: Address | null;
  card: Card | null;         // null until the PSP confirms the charge
};

type PaymentEvent = {
  eventId: string;
  event:
    | "payment.created"
    | "payment.pending"
    | "payment.authorized"
    | "payment.succeeded"
    | "payment.failed"
    | "payment.voided";
  type: "payment";
  apiVersion: string;
  environment: "live" | "test";
  createdAt: string;
  data: PaymentData;
};

Refund payload (type: "refund")

Fires for: payment.partially_refunded, payment.refunded, payment.refund_failed. The envelope type is "refund": data is the refund, and the payment it was issued against is nested at data.payment (the full payment shape from above).

{
  "eventId": "01HXX...",
  "event": "payment.refunded",
  "type": "refund",
  "apiVersion": "2026-05-01",
  "environment": "live",
  "createdAt": "2026-05-22T16:10:11.000Z",
  "data": {
    "id": "rfd_01HXX...",
    "externalId": "refund_order_123_full",
    "status": "succeeded",
    "amount": 49.99,
    "currency": "USD",
    "providerRefundId": "provider_rfn_abc",
    "failureCode": null,
    "failureMessage": null,
    "payment": {
      "id": "pmt_01HXX...",
      "externalId": "order_123",
      "status": "refunded",
      "amount": 49.99,
      "currency": "USD",
      "providerTransactionId": "provider_txn_abc",
      "failureCode": null,
      "failureMessage": null,
      "amountRefunded": 49.99,
      "amountRefundable": 0,
      "customer": {
        "id": "cust_01HXX...",
        "externalId": "cust_42",
        "email": "buyer@example.com",
        "name": "Jane Doe",
        "phone": "+15551234567"
      },
      "billingAddress": {
        "country": "US",
        "postalCode": "10001",
        "name": "Jane Doe",
        "line1": "1 Madison Ave",
        "line2": null,
        "city": "New York",
        "state": "NY"
      },
      "card": {
        "brand": "mastercard",
        "first6": "555544",
        "last4": "0000",
        "mask": "555544******0000",
        "expMonth": "12",
        "expYear": "2030"
      }
    }
  }
}

The refund object carries providerRefundId, failureCode, and failureMessage; on a payment.refund_failed event the failure fields describe the refund (the nested payment keeps its own status). There is no reason or createdAt field on the webhook refund object.

Subscription payload (type: "subscription")

Fires for: subscription.succeeded, subscription.failed, subscription.cancelled. The customer, billing address, and card live on the nested payment object — not at the subscription root. The billing schedule (phases) is returned by the REST API, not on the webhook.

{
  "eventId": "01HXX...",
  "event": "subscription.succeeded",
  "type": "subscription",
  "apiVersion": "2026-05-01",
  "environment": "live",
  "createdAt": "2026-05-22T08:00:00.000Z",
  "data": {
    "id": "sub_01HXX...",
    "externalId": "sub_cust42_plan_pro",
    "status": "active",
    "amount": 19.99,
    "currency": "USD",
    "billingIntervalDays": 30,
    "currentPeriodStart": "2026-05-22T08:00:00.000Z",
    "currentPeriodEnd": "2026-06-21T08:00:00.000Z",
    "cancelledAt": null,
    "payment": {
      "id": "pmt_01HXX...",
      "externalId": "sub_initial_sub_cust42_plan_pro",
      "status": "succeeded",
      "amount": 19.99,
      "currency": "USD",
      "providerTransactionId": "provider_txn_abc",
      "failureCode": null,
      "failureMessage": null,
      "amountRefunded": 0,
      "amountRefundable": 19.99,
      "customer": {
        "id": "cust_01HXX...",
        "externalId": "cust_42",
        "email": "buyer@example.com",
        "name": "Jane Doe",
        "phone": "+15551234567"
      },
      "billingAddress": {
        "country": "US",
        "postalCode": "10001",
        "name": "Jane Doe",
        "line1": "1 Madison Ave",
        "line2": null,
        "city": "New York",
        "state": "NY"
      },
      "card": {
        "brand": "mastercard",
        "first6": "555544",
        "last4": "0000",
        "mask": "555544******0000",
        "expMonth": "12",
        "expYear": "2030"
      }
    }
  }
}

cancelledAt is null until the subscription is cancelled, then an ISO 8601 timestamp. status reflects the subscription's own state (active, past_due, cancelled, …), independent of the nested payment's status.