Payment Notification API

In the SNAP-based Core API flow, Midtrans will call Payment Notification API on the merchant side to send payment notifications. Merchant should implement this Payment Notification API as stated in the contract below.

📘

Midtrans will generate a pair of private and public key for signature generation and share the public key to merchant. Merchant will then need to give Midtrans a partner id that will be used in request header as X-PARTNER-ID.

🚧

Please make sure to whitelist this set of IPs to be able to accept notification from Midtrans.

    <th style={{ textAlign: "left" }}>
      IPs
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td style={{ textAlign: "left" }}>
      Staging
    </td>

    <td style={{ textAlign: "left" }}>
      3.1.141.98/32

      52.76.190.190/32

      13.251.192.204/32

      8.215.39.156/32

      8.215.77.79/32

      147.139.213.119/32

      8.215.56.11/32

      8.215.39.87/32

      8.215.42.0/32

      8.215.59.158/32

      149.129.222.246/32

      8.215.26.108/32

      8.215.13.84/32
    </td>
  </tr>

  <tr>
    <td style={{ textAlign: "left" }}>
      Sandbox
    </td>

    <td style={{ textAlign: "left" }}>
      34.142.147.133/32

      34.142.169.131/32

      34.142.231.22/32

      35.240.161.215/32

      34.142.227.232/32

      34.124.184.175/32

      35.197.130.2/32

      34.142.233.114/32

      8.215.26.211/32

      8.215.22.135/32

      8.215.93.92/32

      8.215.93.214/32

      8.215.93.76/32

      8.215.33.37/32

      8.215.26.148/32

      8.215.194.225/32

      8.215.12.199/32

      149.129.255.111/32
    </td>
  </tr>

  <tr>
    <td style={{ textAlign: "left" }}>
      Production
    </td>

    <td style={{ textAlign: "left" }}>
      13.228.166.126/32

      52.220.80.5/32

      3.1.123.95/32

      8.215.30.222/32

      147.139.209.49/32

      8.215.32.142/32

      147.139.163.77/32

      8.215.25.24/32

      8.215.3.193/32

      147.139.210.20/32

      149.129.238.95/32

      8.215.9.206/32

      147.139.134.22/32
    </td>
  </tr>
</tbody>
Environment
⚠️

Notes on Future Compatibility and Best Practices

To ensure your integration remains robust and scalable, please be aware that Midtrans may introduce additional parameters to the payment notification payload in the future, most likely under the additionalInfo section, but not limited to it. These enhancements are designed to provide greater flexibility and support for evolving business needs.

To prevent any issues caused by these future changes, we strongly recommend that merchants always perform signature verification on the entire payload, rather than validating fields individually. This practice ensures a seamless, secure, and simple implementation that can adapt to future updates without requiring significant changes on your side.

Receiving payment notifications for GoPay and GoPay Tokenization (non Pre-Auth) transaction

This section will describe how merchant should implement payment notification API for GoPay and GoPay Tokenization (non-Pre Auth) transactions for Midtrans to call.

Path/{version}/debit/notify
HTTP MethodPOST
Versionv1.0
SNAP Service Code56

Request Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
X-SIGNATUREStringMCreated using asymmetric signature

Asymmetric-Signature format:

SHA256withRSA (privateKey, stringToSign) with

stringToSign = HTTPMethod +”:“+ EndpointUrl +":“+ Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":“ + TimeStamp

X-PARTNER-IDStringMUnique identifier for partner
X-EXTERNAL-IDStringMNumeric string. Reference number that should be unique in the same day or 1 day idempotency key
Content-type:application/json
X-TIMESTAMP:2024-03-19T14:30:00+07:00
X-SIGNATURE: da1fa417c72d6b91c257e01e54fac824
X-PARTNER-ID: 
X-EXTERNAL-ID:12345678901234567890
CHANNEL-ID:12345

Request Body

Field NameField TypeMandatoryField Description
createdTimeStringOTransaction created timestamp
latestTransactionStatusStringMLatest transaction statusPossible Values:
  • 00 - Success
  • 03 - Pending
  • 04 - Refunded
  • 05 - Canceled
  • 06 - Failure
  • 08 - Expiry
  • 09 - Rejected
originalReferenceNoStringMTransaction identifier on service provider system. For e.g: GopayOrderId
finishedTimeStringOTransaction completed timestamp (for latestTranscationStatus = 00)
originalPartnerReferenceNoStringOOriginal transaction identifier on service consumer system. (Merchant’s orderId)
originalExternalIdString(36)OOriginal External-ID on header message when doing charge (/payment-host-to-host)
merchantIdStringOMerchant ID
amountObjectOTransaction amount
amount.valueStringMTransaction amount
amount.currencyStringMTransaction currency
additionalInfoObjectMAdditional info
additionalInfo.refundHistoryArray of ObjectCArray of refund transactions. Only available if transaction status is refund
additionalInfo.refundHistory.refundNoStringMUnique identifier of refund transaction generated by provider.
additionalInfo.refundHistory.refundStatusStringMRefund status. Possible values:
  • 00 --> Refund success
  • 06 --> Refund failed
additionalInfo.refundHistory.partnerRefundNoStringMUnique identifier of refund transaction generated by client.
additionalInfo.refundHistory.refundAmountObjectMRefund amount
additionalInfo.refundHistory.refundAmount.valueStringMNet amount of the refund. If it's IDR then the value includes 2 decimal digits.

e.g. IDR 10.000,- will be placed with 10000.00

additionalInfo.refundHistory.refundAmount.currencyStringMCurrency
additionalInfo.refundHistory.reasonStringMRefund reason
additionalInfo.refundHistory.refundTimeStringMRefund time
additionalInfo.totalRefundAmountObjectCTotal refund amount. Only available if transaction status is refund or partial refund.
additionalInfo.totalRefundAmount.valueStringMTotal refund amount. If it's IDR then the value includes 2 decimal digits.

e.g. IDR 10.000,- will be placed with 10000.00

additionalInfo.totalRefundAmount.currencyStringMCurrency
additionalInfo.userPaymentDetailsArray of objectMPayment option used by user. This will be not available for deeplink redirection payment flow with pending status.
additionalInfo.userPaymentDetails.payMethodStringMPayment method used by user. E.g: gopay
additionalInfo.userPaymentDetails.payOptionStringMPayment option used by user.
Possible value:
- GoPay = GOPAY_WALLET
- GoPay Later = PAY_LATER
- GoPay Tabungan by Jago = GOPAY_SAVINGS
{
    "createdTime": "2020-01-01T00:00:00+07:00",
    "latestTransactionStatus": "00",
    "originalReferenceNo": "gopayOrderId",
    "finishedTime": "2020-01-02T00:00:00+07:00",
    "originalPartnerReferenceNo": "merchant-order-id",
    "transactionStatusDesc": "desc",
   "originalExternalId":"merchant-order-id",
    "additionalInfo": { 
        "userPaymentDetails": [
         {
           "payMethod": "gopay",
           "payOption": "GOPAY_WALLET"
         }
        ],
         "refundHistory":[
  	{
     	     	"refundNo":"96194816941239812",
      			"refundStatus":"00",
     	     	"partnerReferenceNo":"239850918204981205970",
          		"refundAmount":{
          	   	     	"value":"12345678.00",
         	    	     	"currency":"IDR"
     	     	},
     	     	"refundDate":"2020-12-23T07:44:16+07:00",
          		"reason":"Customer Complain"
  	}
   ]
    }
}

Response Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
Content-type: application/json
X-TIMESTAMP: 2024-03-19T14:30:00+07:00

Response Body

Field NameField TypeMandatoryField Description
responseCodeString (7)MError code to specify the error returned.
responseMessageString (150)MDebug message to provide more information.
{
   "responseCode":"2005600",
   "responseMessage":"Request has been processed successfully"
}


Receiving payment notifications for GoPay QRIS transaction

This section will describe how merchant should implement payment notification API for GoPay QRIS transactions for Midtrans to call.

Path/{version}/qr/qr-mpm-notify
HTTP MethodPOST
Versionv1.0
SNAP service code52

Request Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
X-SIGNATUREStringMCreated using asymmetric signature

Asymmetric-Signature format :

SHA256withRSA (privateKey, stringToSign) with

stringToSign = HTTPMethod +”:“+ EndpointUrl +":“+ Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":“ + TimeStamp

X-PARTNER-IDStringMUnique identifier for caller
X-EXTERNAL-IDStringMNumeric string. Reference number that should be unique in the same day or 1 day idempotency key
Content-type:application/json
X-TIMESTAMP:2020-01-01T00:00:00+07:00
X-SIGNATURE: da1fa417c72d6b91c257e01e54fac824
X-PARTNER-ID: 
X-EXTERNAL-ID:12345678901234567890

Request Body

Field NameField TypeMandatoryField Description
originalReferenceNoStringMTransaction identifier on service provider system. For e.g: GopayOrderId
originalPartnerReferenceNoStringOOriginal transaction identifier on service consumer system. (Merchant’s orderId)
latestTransactionStatusStringMLatest transaction statusPossible Values:
  • 00 - Success
  • 03 - Pending
  • 04 - Refunded
  • 05 - Canceled
  • 06 - Failure
  • 08 - Expiry
  • 09 - Rejected
amountObjectOAmount of the order
amount.valueStringMTransaction amount
amount.currencyStringMTransaction currency
additionalInfoObjectMAdditional info
additionalInfo.refundHistoryArray of ObjectCArray of refund transactions. Only available if transaction status is refund
additionalInfo.refundHistory.refundNoStringMUnique identifier of refund transaction generated by provider.
additionalInfo.refundHistory.partnerReferenceNoStringMUnique identifier of refund transaction generated by client.
additionalInfo.refundHistory.refundAmountObjectMRefund amount
additionalInfo.refundHistory.refundAmount.valueStringMNet amount of the refund. If it's IDR then the value includes 2 decimal digits.

e.g. IDR 10.000,- will be placed with 10000.00

additionalInfo.refundHistory.refundAmount.currencyStringMCurrency
additionalInfo.refundHistory.reasonStringMRefund reason
additionalInfo.refundHistory.refundDateStringMRefund time
additionalInfo.qrisArray of ObjectCArray of QRIS transaction information, based on ASPI's regulation
additionalInfo.qris.issuerNameStringMIssuer company for the payment process
additionalInfo.qris.acquirerNameStringMAcquirer company for the payment process
additionalInfo.qris.transactionTypeStringMASPI Transaction type based on the combination of issuer and acquirer (if the issuer and acquirer is the same will be ON-US, if it's different will become OFF-US)
{
   "originalReferenceNo":"2020102977770000000009",
   "originalPartnerReferenceNo":"2020102900000000000001",
   "latestTransactionStatus":"00",
   "transactionStatusDesc":"success",
   "amount":{
      "value":"12345678.00",
      "currency":"IDR"
   },
   "externalStoreID":"124928924949487",
   "additionalInfo":{
     "qris" :{
       "issuerName":"gopay"
       "acquirerName":"gopay"
       "transactionType":"ON-US"
     }
   }
}

Response Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
Content-type: application/json
X-TIMESTAMP: 2024-03-19T14:30:00+07:00

Response Body

Field NameField TypeMandatoryField Description
responseCodeString (7)MError code to specify the error returned.
responseMessageString (150)MDebug message to provide more information.
{
   "responseCode":"2005200",
   "responseMessage":"Request has been processed successfully"
}

List of response code

Response CodeHTTP StatusDescription
2005200200Successful
2025200202Transaction still on process
4005200400General request failed error, including message parsing failed.
4005201400Invalid format
4005202400Missing or invalid format on mandatory field
4015200401General unauthorized error (No Interface Def, API is Invalid, Oauth Failed, Verify Client Secret Fail, Client Forbidden Access API, Unknown Client, Key not Found)
4015201401Token found in request is invalid (Access Token Not Exist, Access Token Expiry)
4015203401Token not found in the system. This occurs on any API that requires token as input parameter
4035200403Transaction expired
4035201403This merchant is not allowed to call Direct Debit APIs
4035202403Exceeds Transaction Amount Limit
4035203403Suspected Fraud
4035204403Too many request, Exceeds Transaction Frequency Limit
4035205403Account or User status is abnormal
4035206403Cut off In Progress
4035209403The account is dormant
4035214403Insufficient Funds
4035215403Transaction Not Permitted
4035216403Suspend Transaction
4035218403Indicates inactive account
4035219403Merchant is suspended from calling any APIs
4035220403Merchant aggregated purchase amount on that day exceeds the agreed limit
4035221403Set limit not allowed on particular token
4035222403The token limit desired by the merchant is not within the agreed range between the merchant and the Issuer
4035223403Account aggregated purchase amount on that day exceeds the agreed limit
4045200404Invalid transaction status
4045201404Transaction not found
4045202404Invalid Routing
4045204404Transaction is cancelled by customer
4045208404Merchant does not exist or status abnormal
4045210404Invalid API transition within a journey
4045213404The amount doesn't match with what supposed to
4045216404Partner number can't be found
4045217404Terminal does not exist in the system
4045218404Inconsistent request parameter
4055200405Requested function is not supported
4055201405Requested operation to cancel/refund transaction Is not allowed at this time.
4095200409Cannot use same X-EXTERNAL-ID in same day
4095201409Transaction has previously been processed indicates the same partnerReferenceNo already success
4295200429Maximum transaction limit exceeded
5005200500General Error
5005201500Unknown Internal Server Failure, Please retry the process again
5005202500Backend system failure, etc
5045200504timeout from the issuer

Receiving payment notifications for Bank Transfer (VA)

This section will describe how merchant should implement payment notification API for Bank Transfer (VA) transactions for Midtrans to call.

Path/{version}/transfer-va/payment
HTTP MethodPOST
Versionv1.0
SNAP service code25

Request Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
X-SIGNATUREStringMCreated using asymmetric signature

Asymmetric-Signature format :

SHA256withRSA (privateKey, stringToSign) with

stringToSign = HTTPMethod +”:“+ EndpointUrl +":“+ Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":“ + TimeStamp

X-PARTNER-IDStringMUnique identifier for caller
X-EXTERNAL-IDStringMNumeric string. Reference number that should be unique in the same day or 1 day idempotency key
Content-type:application/json
X-TIMESTAMP:2020-01-01T00:00:00+07:00
X-SIGNATURE:da1fa417c72d6b91c257e01e54fac824
X-PARTNER-ID:G12345678
X-EXTERNAL-ID:12345678901234567890

Request Body

Field NameField TypeMandatoryField Description
partnerServiceIdString(8)MpartnerServiceId from the virtual account number
customerNoString(20)McustomerNo from the virtual account number
virtualAccountNoString(28)MVirtual account number for the transaction
virtualAccountNameString(255)OThe customer name
virtualAccountEmailString(255)OThe customer’s email
virtualAccountPhoneString(30)OThe customer’s phone number
trxIdString(64)MThis value will be the trxId used in the create VA request.
paymentRequestIdStringCUnique identifier for this Payment from Midtrans.

This value will exist if the payment has been completed

paidAmountObjectCAmount paid for this transaction

This value will exist if the payment has been completed

paidAmount.valueString(16, 2)MThe numeric string of the amount up to two decimal places
paidAmount.currencyString(3)MThe currency of the value paid. Should be IDR
referenceNoStringOPayment auth code generated by Midtrans
additionalInfoObjectO
additionalInfo.bankStringMIndicates the bank chosen to create the VA at. The banks that can be used will differ based on the banks chosen by the merchant during the onboarding process. Possible values are
  • Permata
  • BCA
  • Mandiri
  • CIMB
  • BNI
  • BRI
additionalInfo.merchantIdString(10)MThis is the merchantId shared by Midtrans during the onboarding process
additionalInfo.paymentFlagStatusString(2)MStatus for Payment Flag

00 - Success

01 - Initiated

02 - Paying

03 - Pending

04 - Refunded

05 - Canceled

06 - Failed

07 - Not found

08 - Expired

09 - Denied

additionalInfo.paidTimeStringMTime when transaction is settled.
additionalInfo.customFieldObjectMA collection of up to three fields sent by the merchant. It will also be displayed on the Dashboard under “order detail”
additionalInfo.customField.1String(255)MFirst field that contains the custom data set by the merchant
additionalInfo.customField.2String(255)MSecond field that contains the custom data set by the merchant
additionalInfo.customField.3String(255)MThird field that contains the custom data set by the merchant
{
    "partnerServiceId":"  088899",
    "customerNo":"12345678901234567890",
    "virtualAccountNo":"  08889912345678901234567890",
    "virtualAccountName":"Jokul Doe",
    "virtualAccountEmail":"[email protected]",
    "virtualAccountPhone":"6281828384858",
    "trxId":"abcdefgh1234",
    "paymentRequestId":"abcdef-123456-abcdef",
    "paidAmount":{
       "value":"12345678.00",
       "currency":"IDR"
    },
    "referenceNo":"123456789012345",
    "additionalInfo":{
       "bank":"BCA",
       "paymentFlagStatus": "00",
       "merchantId":"G059876677",
       "paidTime":"2020-01-01T00:00:00+07:00",  
       "customField": {
          "1": "custom-field-1",
          "2": "custom-field-2",
          "3": "custom-field-3"
       }
    }
 }

Response Header

Field NameField TypeMandatoryField Description
Content-typeStringMMedia type of the resource, i.e. application/json
X-TIMESTAMPStringMClient’s current local time in ISO-8601 format
Content-type:application/json
X-TIMESTAMP:2020-01-01T00:00:00+07:00

Response Body

Field NameField TypeMandatoryField Description
responseCodeString(7)MResponse code
responseMessageString(150)MResponse description
virtualAccountDataObjectM
virtualAccountData.partnerServiceIdString(8)MpartnerServiceId from Create VA Response
virtualAccountData.customerNoString(29)McustomerNo from Create VA Response
virtualAccountData.virtualAccountNoString(28)MVirtual account number for the transaction
virtualAccountData.trxIdString(64)MThis value will be the trxId used in the create VA request.
{
    "responseMessage": "Successful",
    "responseCode": "2002500",
    "virtualAccountData": {
        "partnerServiceId": "  088899",
        "customerNo": "12345678901234567890",
        "virtualAccountNo": "  08889912345678901234567890",
        "trxId": "midtrans-testing-001"
}

List of response code

Response CodeHTTP StatusDescription
2002500200Success
4002500400Bad Request
4002501400Invalid Field Format X-TIMESTAMP
4002502400Invalid Mandatory Field
4012500401Unauthorized. Signature
4042513404Invalid Amount
5002500500Internal Server Error
5042500504Timeout

Notification retry mechanism for Open API

In case we receive an error response when sending notifications to merchants (any non-success response), Midtrans will retry the notification delivery up to a maximum of 5 times with predefined retry intervals. For now, our retry mechanism is as follows:

  • 1st retry delay time = 2 minutes
  • 2nd retry delay time = 10 minutes
  • 3rd retry delay time = 30 minutes
  • 4th retry delay time = 90 minutes (1.5 hours)
  • 5th retry delay time = 210 minutes (3.5 hours)

Notes:

  1. These retry intervals may change at any time as part of continuous improvements. Any changes will be communicated and updated periodically in this documentation.
  2. Midtrans will treat any other responses except HTTP status code 200 as an error