> ## Documentation Index
> Fetch the complete documentation index at: https://docs.singapay.id/llms.txt
> Use this file to discover all available pages before exploring further.

# QRIS Acquirer Webhook

> Real-time notifications for QRIS payment transactions processed through the SingaPay platform. Monitor payment events and keep your system in sync instantly.

<Note>
  **Money In Operation** — This webhook fires when a customer completes a QRIS payment, transferring funds into your SingaPay account.
</Note>

## Information

<div className="overflow-x-auto">
  | Method                                                                                                              | Path                                | Format | Authentication        |
  | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------ | --------------------- |
  | <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-bold bg-blue-500 text-white">POST</span> | `https://your-webhook-url/callback` | json   | HMAC SHA512 Signature |
</div>

SingaPay sends a `POST` request to your configured `transaction_notif_url` when a QRIS transaction is successfully processed.

<Info>
  This webhook may share a callback URL with other event types. See [Shared webhook endpoints](/api-reference/webhooks/shared-endpoints) for routing by `event` value.
</Info>

***

## Request Details

### Headers

| Field           | Value                     | Type         | Mandatory | Description                                                                |
| --------------- | ------------------------- | ------------ | :-------: | -------------------------------------------------------------------------- |
| `Content-Type`  | `application/json`        | Alphabetic   |    Yes    | Specifies JSON format for the request body                                 |
| `User-Agent`    | `SingaPaymentGateway/1.0` | Alphabetic   |    Yes    | Identifies the source of the webhook                                       |
| `Accept`        | `application/json`        | Alphabetic   |    Yes    | Expected response format                                                   |
| `X-PARTNER-ID`  | —                         | Alphanumeric |    Yes    | Your API Key from the merchant dashboard                                   |
| `X-Signature`   | —                         | Alphanumeric |    Yes    | HMAC SHA512 signature (128 chars) for request verification                 |
| `X-Timestamp`   | —                         | Numeric      |    Yes    | Unix timestamp in **seconds** when the request was sent                    |
| `Authorization` | `Bearer <random_token>`   | Alphanumeric |    Yes    | System-generated random bearer token; used as a component in the signature |

<Note>
  The `Authorization` token for QRIS webhooks is a **randomly generated string** — not a user access token. This webhook is triggered by a bank payment notification (system event), not a user action. Extract the token as-is from the header and use it in the string to sign. See [How to Validate Signature](#how-to-validate-signature) below.
</Note>

***

### Body Parameters

<ParamField body="status" type="number" required>
  HTTP Status Code. Example: `200`
</ParamField>

<ParamField body="success" type="boolean" required>
  Indicates if the transaction was successful. Example: `true`
</ParamField>

<ParamField body="event" type="string" required>
  Event type identifier. Always `"qris-acquirer-transaction"` for this webhook.
</ParamField>

<ParamField body="timestamp" type="string" required>
  Event timestamp in format `"d M Y H:i:s"`. Example: `"26 Dec 2025 13:31:59"`
</ParamField>

<ParamField body="data" type="object" required>
  Container for transaction, customer, and payment details.

  <Expandable title="data fields">
    <ParamField body="transaction" type="object" required>
      Transaction details.

      <Expandable title="transaction fields">
        <ParamField body="id" type="integer" required>
          Unique transaction ID. Example: `42`
        </ParamField>

        <ParamField body="reff_no" type="string" required>
          Unique transaction reference number (28 chars). Example: `"6601K62BH34X445J046C4W5249E6"`
        </ParamField>

        <ParamField body="merchant_reff_no" type="string">
          Optional merchant reference number for tracing. Example: `"INV-2026-001"`
        </ParamField>

        <ParamField body="type" type="string" required>
          Transaction type. Always `"qris"` for QRIS transactions.
        </ParamField>

        <ParamField body="status" type="string" required>
          Transaction status. Always `"paid"` for this webhook.
        </ParamField>

        <ParamField body="amount" type="object" required>
          Base transaction amount before tip.

          <Expandable title="amount fields">
            <ParamField body="value" type="number" required>Base transaction amount. Example: `1000123`</ParamField>
            <ParamField body="currency" type="string" required>ISO 4217 currency code. Example: `"IDR"`</ParamField>
          </Expandable>
        </ParamField>

        <ParamField body="tip" type="object" required>
          Tip amount details.

          <Expandable title="tip fields">
            <ParamField body="value" type="number" required>Tip amount. `0` if no tip. Example: `0`</ParamField>
            <ParamField body="currency" type="string" required>ISO 4217 currency code. Example: `"IDR"`</ParamField>
          </Expandable>
        </ParamField>

        <ParamField body="total_amount" type="object" required>
          Total amount including tip (`amount + tip`).

          <Expandable title="total_amount fields">
            <ParamField body="value" type="number" required>Total transaction amount. Example: `1000123`</ParamField>
            <ParamField body="currency" type="string" required>ISO 4217 currency code. Example: `"IDR"`</ParamField>
          </Expandable>
        </ParamField>

        <ParamField body="post_timestamp" type="string" required>
          Transaction post time. Example: `"26 Dec 2025 13:31:59"`
        </ParamField>

        <ParamField body="processed_timestamp" type="string" required>
          Transaction processed time. Example: `"26 Dec 2025 13:31:59"`
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="customer" type="object" required>
      Customer details.

      <Expandable title="customer fields">
        <ParamField body="id" type="string" required>Customer unique ID (26 chars). Example: `"01K2KVRQQP45234X9T3YWG1FKT"`</ParamField>
        <ParamField body="name" type="string" required>Customer full name. Example: `"Moh. Zulkifli Katili"`</ParamField>
        <ParamField body="email" type="string" required>Customer email address. Example: `"tes@gmail.com"`</ParamField>
        <ParamField body="phone" type="string" required>Customer phone number. Example: `"08123993201"`</ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="payment" type="object" required>
      Payment method details.

      <Expandable title="payment fields">
        <ParamField body="method" type="string" required>
          Payment method. Always `"qris"`.
        </ParamField>

        <ParamField body="additional_info" type="object" required>
          QRIS-specific payment information.

          <Expandable title="additional_info fields">
            <ParamField body="qr_string" type="string" required>
              Raw QRIS string data used for payment. Example: `"00020101021226570015ID.SINGAPAY.WWW..."`
            </ParamField>

            <ParamField body="payment_event_id" type="number" required>
              Internal payment event ID for tracking. Example: `12345`
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

***

### Payload Example

```json Success theme={null}
{
  "status": 200,
  "success": true,
  "event": "qris-acquirer-transaction",
  "timestamp": "26 Dec 2025 13:31:59",
  "data": {
    "transaction": {
      "id": 42,
      "reff_no": "6601K62BH34X445J046C4W5249E6",
      "merchant_reff_no": "INV-2026-001",
      "type": "qris",
      "status": "paid",
      "amount": {
        "value": 1000123,
        "currency": "IDR"
      },
      "tip": {
        "value": 0,
        "currency": "IDR"
      },
      "total_amount": {
        "value": 1000123,
        "currency": "IDR"
      },
      "post_timestamp": "26 Dec 2025 13:31:59",
      "processed_timestamp": "26 Dec 2025 13:31:59"
    },
    "customer": {
      "id": "01K2KVRQQP45234X9T3YWG1FKT",
      "name": "Moh. Zulkifli Katili",
      "email": "tes@gmail.com",
      "phone": "08123993201"
    },
    "payment": {
      "method": "qris",
      "additional_info": {
        "qr_string": "00020101021226570015ID.SINGAPAY.WWW01110508140001102122183098102390303UMI51440014ID.CO.QRIS.WWW02157434441747371980303UMI520472315303360540710001235802ID5916PT TARSIUS TAHIR6009Tangerang6105544786253051017588683110703C0108286601K62BH34X445J046C4W5249E663045FC6",
        "payment_event_id": 12345
      }
    }
  }
}
```

***

***

## Security and responses

Return HTTP `200` promptly after validating the request. For retry behavior, see [Webhook retry mechanism](/api-reference/webhooks/retry-mechanism).

Verify every webhook using [Security and signature validation](/api-reference/webhooks/security-and-signature). Use your configured callback path when building `StringToSign`.

Handle duplicate deliveries idempotently using stable identifiers from the payload (for example `transaction_id` or `reff_no`).
