Paycose Docs
FlowEvents

Charge events

What data you get for charge.created, charge.paid, charge.captured, charge.canceled, charge.expired, charge.refunded, and charge.requires_action.

Fires as a charge moves through its lifecycle — created, paid, captured, canceled or expired, refunded, or waiting on an extra step from the payer.

Prop

Type

charge.created

Sent right after a charge is opened, usually still pending.

{
  "id": "ch_01J9ABCDEFGHJKMNPQRSTV",
  "object": "charge",
  "status": "pending",
  "customer_id": "cus_01J8XYZABCDEFGHJKMNPQR",
  "payment_method_id": "pm_01J8XYZABCDEFGHJKMNPQR",
  "amount": 150000,
  "currency": "THB",
  "scaling_factor": 100,
  "paid": false,
  "canceled": false,
  "refunded": false,
  "captured": false,
  "capture_method": "automatic",
  "settlement_status": "pending",
  "disputed": false,
  "provider": "omise",
  "metadata": { "order_id": "SO-2026-0042" },
  "payment_method": {
    "id": "pm_01J8XYZABCDEFGHJKMNPQR",
    "type": "card",
    "brand": "visa",
    "issuer": "kbank",
    "last4": "4242"
  }
}

amount is in the currency's minor unit — divide by scaling_factor for a display value.

charge.paid and charge.captured

Same shape as above. On charge.paid, status is "succeeded" and paid is true. On charge.captured, captured is true and amount_captured reflects the captured amount (which may be less than amount on a partial capture).

charge.canceled and charge.expired

Same shape, status becomes "failed" and canceled is true. charge.expired fires instead of charge.canceled when the cancellation was caused by something timing out (a QR code, a redirect, a session) rather than an explicit cancel:

{
  "id": "ch_01J9ABCDEFGHJKMNPQRSTV",
  "object": "charge",
  "status": "failed",
  "canceled": true,
  "failure_reason": "qr_expired",
  "failure_code": "expired",
  "failure_message": "The QR code expired before payment was completed.",
  "canceled_at": "2026-07-25T17:35:00Z",
  "currency": "THB",
  "amount": 150000
}

charge.refunded

Sent when a refund on the charge succeeds, fully or partially — the same event as Stripe's. amount_refunded is the total refunded so far, and refunded turns true once the whole charge has been refunded. A partial refund leaves the rest refundable, so the event can fire more than once for the same charge.

{
  "id": "ch_01J9ABCDEFGHJKMNPQRSTV",
  "object": "charge",
  "status": "succeeded",
  "amount": 150000,
  "amount_captured": 150000,
  "amount_refunded": 50000,
  "currency": "THB",
  "scaling_factor": 100,
  "paid": true,
  "captured": true,
  "refunded": false,
  "provider": "omise"
}

The refund itself arrives as refund.created and refund.updated.

charge.requires_action

The one event where next_action is populated — a provider is asking the payer to complete an extra step (3DS challenge, bank redirect, app confirmation) before the charge can settle.

{
  "id": "ch_01J9ABCDEFGHJKMNPQRSTV",
  "object": "charge",
  "status": "pending",
  "amount": 150000,
  "currency": "THB",
  "next_action": [
    {
      "type": "redirect",
      "title": "Complete authentication",
      "description": "Confirm the payment in your banking app.",
      "url": "https://api.omise.co/payments/authorize/xyz"
    }
  ],
  "payment_method": {
    "type": "card",
    "brand": "visa",
    "last4": "4242"
  }
}

On this page