Z Zise Developers 简体中文

card.transaction.updated

Card transaction received or its status updated

When Emitted

Sent after processing a normal transaction callback, automatic reconciliation, or an operations query that backfills a record. data.id is the ctx_ resource ID from the transaction list; data.card_id is the crd_ card ID. Retrieve through GET /v1/cards/{id}/transactions. authorized means authorized and awaiting settlement; do not treat it as settled. Identical snapshots of the same local transaction use the same event_id; recipients must deduplicate by event_id. Sandbox transaction simulation uses the same processing flow, with notifications delivered in the sandbox environment. bank_fee is the bank fee; zinfra_fee is the zinfra fee, currently "0" for all cards. Both are integer strings in minor units, with currency and precision supplied by fee_currency and fee_scale. These are cumulative transaction fee snapshots, not additional fees charged for each notification; authorization fees may change at settlement. original_amount / original_currency preserve the upstream transaction’s original currency and amount text. bill_amount is the card-currency bill amount, an integer string in minor units using the same source as the list: the stored settlement amount or authorization hold, without on-demand currency conversion. bill_amount is omitted when no bill amount is known. GET /v1/cards/{id}/transactions remains authoritative for details.

This event is not initiated by an API call

Triggered by a scheduled job or a provider callback.

Payload

{
  "event_id": "evt_06a0d3fbbe074aa98809e2b90588b123",
  "event_type": "card.transaction.updated",
  "created_at": "2026-09-08T05:45:00Z",
  "merchant_id": "acme",
  "livemode": true,
  "data": {
    "object": "card_transaction",
    "id": "ctx_11111111-2222-4333-8444-555555555555",
    "card_id": "crd_aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
    "external_member_id": "u_88123",
    "status": "authorized",
    "status_version": 1788846300000,
    "bank_fee": "30000",
    "zinfra_fee": "0",
    "fee_currency": "USD",
    "fee_scale": 6,
    "original_amount": "8.0000",
    "original_currency": "HKD",
    "bill_amount": "1020000"
  }
}

Payload Fields

FieldTypeDescription
idstringUse this for deduplication. evt_… remains unchanged when the same event is redelivered.
typestringAlways card.transaction.updated
created_atstringTime the event was created (RFC3339), not its delivery time. It is unchanged on redelivery.
data.objectstringObject type; determines which endpoint to query with data.id
data.idstringObject ID; use it to retrieve details.
data.statusstringTreat unrecognized values as unknown and raise an alert; do not fall back to “processing”
data.status_versionnumberMonotonically increasing; use it to discard older states that arrive late.

Signature Verification and Deduplication

Verify the signature against the raw request body bytes. Do not parse and reserialize the JSON: your JSON library may change key order or whitespace, which changes the signature and can look like a key configuration error.

// Node · Run before parsing JSON
const raw = await readRawBody(req);            // Buffer / string; do not use parsed req.body
const expect = crypto.createHmac("sha256", WEBHOOK_SECRET).update(raw).digest("hex");
const got = req.headers["z-signature"];        // Format: t=<unix>,v1=<hex>
if (!timingSafeEqual(expect, parseV1(got))) return res.status(400).end();

// Deduplicate using the envelope id, not data.id
if (await seen(JSON.parse(raw).id)) return res.status(200).end();

For the full procedure, including timestamp tolerance and redelivery semantics, see Webhook Guide.