1. Issuing
PIK
  • Start
    • Getting Started
  • Authentication
    • Authentication Token
      POST
  • Global Account
    • Contacts
      • Create Contact
      • List Contacts
      • Get Contact
      • Count Contacts
    • Virtual Accounts
      • Create Virtual Account
      • List Virtual Accounts
      • Get Virtual Account
    • Transactions
      • List Transactions
      • Get Transaction
    • Account Balance
      • List Account Balances
      • Get Balance by Currency
    • Payout
      • Create Payout
  • Payment Links
    • Payment Links
      • Create Payment Link
      • Update Payment Link
      • Get Payment Link Detail
      • Get Payment Link List
    • Transactions
      • Get Transaction List
  • Webhook
    • Global Account
      • Deposit Webhook
      • Payout Webhook
      • Virtual Account Webhook
    • Payment Links
      • Overview
      • Order Collect Out Webhook
      • Customer Payment Webhook
      • Customer Refund Webhook
      • Master Recharge Webhook
      • Web3 Direct Payment Webhook
      • Withdraw Out Webhook
    • Issuing
      • Card Activated
      • Card Failed
      • Transaction Completed
      • Transaction Declined
  • Issuing
    • Card Products
      • List Card Products
    • Cardholders
      • Create Cardholder
      • List Cardholders
      • Get Cardholder
    • Cards
      • Issue Card
      • List Cards
      • Get Card
      • Create Card Secure Session
    • Transactions
      • List Transactions
      • Get Transaction
  1. Issuing

Transaction Completed

transaction.completed — delivered when a purchase, refund or reversal has posted.

When it fires#

Whenever a transaction settles against one of your cards. Because card spending happens outside
your control, this webhook is the primary way you learn about transactions — the query API
is for reconciliation and backfill, not for discovery.
Refunds and reversals carry originalTransactionNo pointing at the transaction being reversed.

Payload#

Envelope#

FieldTypeDescription
eventIdstringUnique per event. Deduplicate on this value
eventTypestringAlways transaction.completed
versionstringPayload schema version. Additive changes do not bump it
occurredAtstringWhen the event happened, not when it was delivered (ISO 8601)
dataobjectThe transaction, see below

data#

Structurally identical to the response of GET /api/v1/issuing/transaction/{transactionNo}, so
a single parser handles both paths.
FieldTypeDescription
transactionNostringPIK transaction number
cardNostringPIK card number
cardholderNostringPIK cardholder number
typestringPURCHASE / REFUND / REVERSAL / ATM_WITHDRAWAL / VERIFICATION / SETTLEMENT_ADJUST
statusstringCOMPLETED for this event
originalTransactionNostringSet on refunds and reversals, otherwise null
transactionAmountstringAmount in the merchant's currency
transactionCurrencystringMerchant currency, ISO 4217
billingAmountstringAmount posted in the card's settlement currency
billingCurrencystringSettlement currency, ISO 4217
fxobjectForeign exchange details, see below
feesarrayItemised fee breakdown, see below
totalFeeAmountstringSum of all fee amounts
totalDebitAmountstringbillingAmount + totalFeeAmount
merchantobjectname / mcc / city / country
transactionTimestringTime the transaction occurred
postedTimestringTime the transaction was posted
declineReasonstringnull for this event

fx#

FieldTypeDescription
isCrossCurrencybooleanWhether the transaction currency differs from the billing currency
ratestringExchange rate applied, billing currency per unit of transaction currency
convertedAmountstringTransaction amount converted at that rate, excluding any fees

fees[]#

FieldTypeDescription
feeCodestringTRANSACTION_FEE / FX_CONVERSION_FEE / ATM_WITHDRAWAL_FEE / CARD_ISSUE_FEE
feeNamestringHuman-readable fee name
amountstringFee amount
currencystringFee currency
baseAmountstringThe amount the fee was calculated on
calcModestringPERCENT / FIXED / MIXED
ratestringRate applied for PERCENT and MIXED
fixedAmountstringFixed component for FIXED and MIXED
minFee / maxFeestringBounds applied, null when unbounded
ruleNo / ruleVersionstring / integerIdentifies the exact pricing rule, for reconciliation
Why baseAmount is not billingAmount. On cross-currency transactions billingAmount is
the figure the card network posts, and it can include network-side surcharges on top of the
conversion. Percentage fees are therefore calculated on fx.convertedAmount — the converted
amount with no fees folded in.

Example — cross-currency purchase#

{
  "eventId": "evt_01J9X8ZQ4T3P",
  "eventType": "transaction.completed",
  "version": "1.0",
  "occurredAt": "2026-08-11T10:20:18+08:00",
  "data": {
    "transactionNo": "TX260811K3M5N1",
    "cardNo": "CD260811X9Y8Z7",
    "cardholderNo": "CH260811A1B2C3",
    "type": "PURCHASE",
    "status": "COMPLETED",
    "originalTransactionNo": null,
    "transactionAmount": "10.00",
    "transactionCurrency": "EUR",
    "billingAmount": "13.10",
    "billingCurrency": "USD",
    "fx": {
      "isCrossCurrency": true,
      "rate": "1.160000",
      "convertedAmount": "11.60"
    },
    "fees": [
      {
        "feeCode": "TRANSACTION_FEE",
        "feeName": "Transaction Fee",
        "amount": "0.12",
        "currency": "USD",
        "baseAmount": "11.60",
        "calcMode": "PERCENT",
        "rate": "0.010000",
        "fixedAmount": "0.00",
        "minFee": null,
        "maxFee": null,
        "ruleNo": "FR-TXN-0001",
        "ruleVersion": 2
      },
      {
        "feeCode": "FX_CONVERSION_FEE",
        "feeName": "FX Conversion Fee",
        "amount": "0.02",
        "currency": "USD",
        "baseAmount": "11.60",
        "calcMode": "PERCENT",
        "rate": "0.002000",
        "fixedAmount": "0.00",
        "minFee": "0.01",
        "maxFee": null,
        "ruleNo": "FR-FX-0001",
        "ruleVersion": 3
      }
    ],
    "totalFeeAmount": "0.14",
    "totalDebitAmount": "13.24",
    "merchant": {
      "name": "STEAM PURCHASE",
      "mcc": "5734",
      "city": "Singapore",
      "country": "SG"
    },
    "transactionTime": "2026-08-11T10:20:15+08:00",
    "postedTime": "2026-08-11T10:20:18+08:00",
    "declineReason": null
  }
}

Example — refund#

{
  "eventId": "evt_01J9X8ZQ4T4R",
  "eventType": "transaction.completed",
  "version": "1.0",
  "occurredAt": "2026-08-12T09:02:11+08:00",
  "data": {
    "transactionNo": "TX260812P7Q2R8",
    "cardNo": "CD260811X9Y8Z7",
    "cardholderNo": "CH260811A1B2C3",
    "type": "REFUND",
    "status": "COMPLETED",
    "originalTransactionNo": "TX260811K3M5N1",
    "transactionAmount": "10.00",
    "transactionCurrency": "EUR",
    "billingAmount": "13.10",
    "billingCurrency": "USD",
    "fx": {
      "isCrossCurrency": true,
      "rate": "1.160000",
      "convertedAmount": "11.60"
    },
    "fees": [],
    "totalFeeAmount": "0.00",
    "totalDebitAmount": "13.10",
    "merchant": {
      "name": "STEAM PURCHASE",
      "mcc": "5734",
      "city": "Singapore",
      "country": "SG"
    },
    "transactionTime": "2026-08-12T09:02:08+08:00",
    "postedTime": "2026-08-12T09:02:11+08:00",
    "declineReason": null
  }
}

Verifying the signature#

Two headers accompany every delivery:
HeaderValue
x-pik-timestampUnix timestamp in seconds
x-pik-signatureHMAC-SHA512 signature, lowercase hex
x-pik-signature = hex_lower( HMAC_SHA512( webhookSecret, rawBody + timestamp ) )
The signed content is the raw body concatenated with the timestamp, no separator.
1.
Sign the raw bytes of the request body, before any JSON parsing.
2.
Compare in constant time.
3.
Reject deliveries whose x-pik-timestamp is more than 300 seconds from your clock.

Delivery#

Return HTTP 200 within 5 seconds to acknowledge.
Failed deliveries are retried with exponential backoff: 10s, 1m, 5m, 30m, 2h, 6h, 24h.
Delivery is at least once — deduplicate on eventId.
Ordering is not guaranteed — use occurredAt to decide which version is newer.
Treat transactionNo as the business key; a transaction can generate several events.
See the Webhooks guide for verification code samples and recommended
handling.
Modified at 2026-08-11 10:12:50
Previous
Card Failed
Next
Transaction Declined
Built with