PayPal - Parse IPN Request
Audience:
Low-code EngineersSkill Prerequisites:
Actions,Tokens,API endpoints
Reads a PayPal Instant Payment Notification (IPN) and turns each of its fields into a token, for example [Ipn:txn_type] or [Ipn:payer_email]. Use it in an API endpoint that PayPal posts its notifications to.
The action only reads the message. It doesn't check with PayPal that the message is genuine, so verify it before you act on it. See Security.
This action is part of the PayPal add-on (DnnSharp.PayPal). The add-on is installed separately and needs the PAYPAL feature in your license. If it isn't licensed, the action fails with a "not licensed" error. If you don't see the PayPal actions, the add-on isn't installed.
Typical Use Cases
- Build your own IPN handler in an API endpoint, for example to record every subscription payment
- Track subscriptions created by PayPal - Express Checkout for longer than its built-in 7-day window
- Parse an IPN message that was saved earlier, for example to reprocess it
Don't use it to
- Confirm that a payment happened. The IPN can be forged. Confirm it with Get Transaction Details.
- Handle Stripe events. Use Stripe Get Event Details instead.
Related Actions
| Action Name | Description |
|---|---|
| PayPal - Express Checkout | Takes the payment or creates the subscription that the IPN reports on. It explains the whole PayPal flow. |
| Get Transaction Details | Asks PayPal for the details of a transaction, for example the txn_id of an IPN. |
| Cancel Express Checkout Subscription | Cancels a subscription by its profile ID. |
| Run SQL Query | Saves the IPN data in your database. |
Input Parameter Reference
| Parameter | Description | Supports Tokens | Default | Required |
|---|---|---|---|---|
| Request Data | The IPN message, URL-encoded, for example recurring_payment_id=I-DF3S35GWL16Y&profile_status=Active&.... Leave it empty to read the body of the current HTTP request, which is what PayPal posts to your API endpoint. | Yes | empty string | No |
| TokenPrefix | Text added in front of every token name, for example Ipn: for [Ipn:payer_email]. It's added as typed, with nothing in between. | Yes | empty string | No |
Output Parameters Reference
The action has no output parameters. It creates one token for every field in the message, named TokenPrefix plus the field name. Values are URL-decoded. PayPal decides which fields it sends, and they depend on the notification type. The action's help text lists these common fields for subscriptions:
recurring_payment_id, profile_status, payer_id, payer_email, payer_status, last_name, first_name, initial_payment_amount, amount, product_name, product_type, payment_cycle, amount_per_cycle, next_payment_date, period_type, receiver_email, time_created, currency_code, residence_country, verify_sign, test_ipn, tax, txn_type, shipping, charset, notify_version, outstanding_balance and ipn_track_id.
The profile_status can be Created, Updated, Active, Suspended or Cancelled. Use txn_type to tell the notification types apart, for example recurring_payment or recurring_payment_profile_cancel.
Security
An IPN handler is a public address, and anyone can post to it. Before you grant access, mark an order as paid or change a subscription, check the message:
- Confirm it with PayPal. For notifications about a payment, look up the
txn_idwith Get Transaction Details and use the status and amount PayPal returns. PayPal also documents a postback check, where you send the message back to PayPal and it answersVERIFIEDorINVALID. You can do that with Server Request. - Check that it's for you. Compare
receiver_emailwith your PayPal account's email. - Handle repeats. PayPal may send the same notification more than once. Save
ipn_track_idortxn_idand skip messages you've already processed.
Considerations
- Always use a prefix. Without one, the fields are saved with their plain names, like
amountorfirst_name, and replace any tokens with the same names. Since the sender chooses the field names, a prefix such asIpn:keeps the message from overwriting your own tokens. - Tell PayPal where to post. Set your API endpoint's URL as the IPN address in your PayPal account's profile, or send it as the notify URL of the payment.
- Reply quickly. PayPal resends a notification if it doesn't get a successful response. If your actions fail with an error, expect the same message again.
- It needs a request. With Request Data empty, the action reads the current HTTP request. Where there's no request, such as a scheduled job, fill in Request Data.
- Test in the sandbox. PayPal's sandbox sends test notifications with
test_ipnset to1. Ignore those in production.
Examples
To understand how to use the below examples, please see Running Examples.
1. Read the IPN that PayPal posted to an API endpoint
This action reads the body of the request and creates tokens that start with Ipn:, for example [Ipn:recurring_payment_id], [Ipn:profile_status] and [Ipn:txn_id].
{
"Title": "PayPal - Parse IPN Request",
"ActionType": "ParseIPNRequest",
"Description": "Read the PayPal notification",
"Parameters": {
"RequestData": "",
"TokenPrefix": "Ipn:"
}
}
2. Confirm a subscription payment before recording it
These actions run after example 1. The first one asks PayPal for the transaction in the IPN, and only for real payments to your account. The second parses PayPal's answer. The third records the payment only if PayPal says it's completed. The credentials come from tokens.
[
{
"Title": "Get Transaction Details",
"ActionType": "PayPal.GetTransactionDetails",
"Description": "Confirm the payment with PayPal",
"Condition": "[Ipn:txn_type] == \"recurring_payment\" && [Ipn:receiver_email] == [PayPalAccountEmail]",
"Parameters": {
"PayPalExpressId": "[PayPalApiUser]",
"PayPalExpressPassword": "[PayPalApiPassword]",
"PayPalExpressSignature": "[PayPalApiSignature]",
"PayPalExpressLiveMode": true,
"TransactionId": "[Ipn:txn_id]",
"JsonToken": "PayPalTransactionJson"
}
},
{
"Title": "Parse JSON Into Tokens",
"ActionType": "ParseJsonIntoTokens",
"Description": "Read PayPal's answer",
"Condition": "[PayPalTransactionJson] != \"\"",
"Parameters": {
"JsonString": "[PayPalTransactionJson]",
"BaseTokenName": "Txn"
}
},
{
"Title": "Run SQL Query",
"ActionType": "RunSql",
"Description": "Record the subscription payment",
"Condition": "[Txn:ACK] == \"Success\" && [Txn:PAYMENTSTATUS] == \"Completed\"",
"Parameters": {
"SqlQuery": "INSERT INTO SubscriptionPayments (ProfileId, TransactionId, Amount, IpnTrackId) VALUES (@ProfileId, @TransactionId, @Amount, @IpnTrackId)",
"BindTokens": [
{
"name": "ProfileId",
"value": "[Ipn:recurring_payment_id]"
},
{
"name": "TransactionId",
"value": "[Ipn:txn_id]"
},
{
"name": "Amount",
"value": "[Txn:AMT]"
},
{
"name": "IpnTrackId",
"value": "[Ipn:ipn_track_id]"
}
]
}
}
]
Revised 09/27/2026