Square payment received notifications on your phone.

Get a push notification with the amount, tip and card when a Square payment completes, from your online checkout, Point of Sale or Terminal.

How it works

Three steps to your first push

STEP 01

Install the recipe

One click in Studio gives you a personal webhook URL.

STEP 02

Paste your URL into Square

Add it as a webhook for payment.updated.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Square payment.updated webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. In the Square Developer Console (developer.squareup.com/apps), open your application (create a free one if you have none) and switch to Production.
  3. Under Webhooks, choose Subscriptions and click Add subscription.
  4. Paste your webhook URL as the notification URL, tick the payment.updated event, and save.https://••••••••/•••••••• your personal URL, shown after install
  5. Subscribe to **payment.updated** only. Square fires it several times per payment (when it's authorised, completed, when processing fees are added, when it's refunded). The recipe pushes only for a completed payment and skips the follow-up updates that carry processing fees or a refund, so you normally get one push per sale.
  6. Square can still send an extra early update for the same payment (for example when it links a customer), which can occasionally give a second push. If you notice Point of Sale or Terminal sales that never push, also tick **payment.created**: the recipe then pushes for payments that are created already completed, at the risk of an extra push for some sales.
  7. Payments on invoices also push here. If you use the Invoice paid recipe as well, you'll get both.
  8. Sandbox and Production have separate webhook subscriptions, so add this one in Production for real sales. Sandbox deliveries are marked **(sandbox)**.
  9. Square signs every notification with an `x-square-hmacsha256-signature` header (an HMAC-SHA256 of your notification URL and the body, keyed with the subscription's signature key), but JustPush doesn't check that signature yet, so keep your endpoint URL private.
The code

What runs when the webhook arrives

Studio calls handleRequest(request) with the incoming webhook and sends the message it returns. It's yours after install; change anything.

transform.js
1// Square → payment.updated (payment completed)
2// Fires when a payment reaches COMPLETED: a card sale, a captured authorisation, a paid
3// invoice or a cleared ACH transfer, from the Square API, Point of Sale or Terminal.
4// Docs: https://developer.squareup.com/docs/payments-api/webhooks
5
6// Square doesn't send an event-name header; the event type is in the body's "type".
7const EVENTS = ["payment.updated", "payment.created"]
8
9// Friendlier names for Square's card brands and payment sources.
10const BRANDS = {
11 VISA: "Visa",
12 MASTERCARD: "Mastercard",
13 AMERICAN_EXPRESS: "American Express",
14 DISCOVER: "Discover",
15 DISCOVER_DINERS: "Diners Club",
16 JCB: "JCB",
17 CHINA_UNIONPAY: "UnionPay",
18 SQUARE_GIFT_CARD: "Square gift card",
19 INTERAC: "Interac",
20 EFTPOS: "eftpos",
21 FELICA: "FeliCa",
22 EBT: "EBT",
23}
24
25const WALLETS = {
26 CASH_APP: "Cash App Pay",
27 PAYPAY: "PayPay",
28 ALIPAY: "Alipay",
29 RAKUTEN_PAY: "Rakuten Pay",
30 AU_PAY: "au PAY",
31 D_BARAI: "d払い",
32 MERPAY: "Merpay",
33 WECHAT_PAY: "WeChat Pay",
34 LIGHTNING: "Bitcoin Lightning",
35}
36
37const BNPL = {
38 AFTERPAY: "Afterpay",
39 CLEARPAY: "Clearpay",
40}
41
42const SOURCES = {
43 CASH: "cash",
44 BANK_ACCOUNT: "bank transfer",
45 SQUARE_ACCOUNT: "Square account",
46 EXTERNAL: "an external method",
47}
48
49// Header names can arrive in any case.
50function header(request, name) {
51 const headers = request.headers || {}
52 const key = Object.keys(headers).find((k) => k.toLowerCase() === name)
53 const value = key ? headers[key] : null
54 return Array.isArray(value) ? value[0] : value
55}
56
57// Table lookup that ignores inherited names such as "toString".
58function pick(table, key, fallback) {
59 return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
60}
61
62// Only link to real http(s) URLs.
63function link(url, cta) {
64 return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
65}
66
67// Square Money is { amount, currency } with amount in the currency's smallest unit
68// (cents for USD/EUR/GBP, whole yen for JPY). Returns null when there's no amount.
69function money(value) {
70 const amount = value?.amount
71 const currency = value?.currency
72
73 if (typeof amount !== "number" || !Number.isFinite(amount) || typeof currency !== "string" || !currency) return null
74
75 try {
76 const format = new Intl.NumberFormat("en-GB", { style: "currency", currency })
77 return format.format(amount / 10 ** format.resolvedOptions().maximumFractionDigits)
78 } catch {
79 return null
80 }
81}
82
83// "via Visa •••• 1111", "via cash", "via Cash App Pay" …
84function method(payment) {
85 if (payment.source_type === "CARD") {
86 const card = payment.card_details?.card ?? {}
87 return pick(BRANDS, card.card_brand, "card") + (card.last_4 ? ` •••• ${card.last_4}` : "")
88 }
89 if (payment.source_type === "WALLET") return pick(WALLETS, payment.wallet_details?.brand, "a digital wallet")
90 if (payment.source_type === "BUY_NOW_PAY_LATER") return pick(BNPL, payment.buy_now_pay_later_details?.brand, "buy now, pay later")
91 return pick(SOURCES, payment.source_type, null)
92}
93
94function handleRequest(request) {
95 const body = request.body && typeof request.body === "object" ? request.body : {}
96 const payment = body.data?.object?.payment
97
98 // Guard: only payment events that carry the payment object.
99 if (!EVENTS.includes(body.type) || !payment || typeof payment !== "object") {
100 console.log(`Ignoring Square event "${typeof body.type === "string" ? body.type : "unknown"}"`)
101 return null
102 }
103
104 // Square sends payment.updated for every change (authorised, completed, fees added,
105 // refunded …). Only a completed payment is worth a push.
106 if (payment.status !== "COMPLETED") {
107 console.log(`Skipping payment with status "${payment.status ?? "unknown"}"`)
108 return null
109 }
110
111 // Follow-up updates for the same payment: Square adds processing fees in a separate
112 // payment.updated after completion, and refunds update refunded_money.
113 if (Array.isArray(payment.processing_fee) && payment.processing_fee.length > 0) {
114 console.log("Skipping follow-up update (processing fees added)")
115 return null
116 }
117 if (payment.refunded_money?.amount > 0) {
118 console.log("Skipping follow-up update (payment was refunded)")
119 return null
120 }
121
122 const total = money(payment.total_money) ?? money(payment.amount_money) ?? "A payment"
123 const tip = payment.tip_money?.amount > 0 ? money(payment.tip_money) : null
124 const via = method(payment)
125 const note = typeof payment.note === "string" && payment.note.trim() ? payment.note.trim().slice(0, 100) : null
126 const sandbox = String(header(request, "square-environment") ?? "").toLowerCase() === "sandbox" ? " (sandbox)" : ""
127
128 return {
129 title: "💰 Payment received",
130 message:
131 total +
132 (tip ? ` (incl. ${tip} tip)` : "") +
133 (via ? ` via ${via}` : "") +
134 (payment.buyer_email_address ? ` from ${payment.buyer_email_address}` : "") +
135 (note ? ` — ${note}` : "") +
136 sandbox,
137 topic: "Square",
138 priority: 0, // Normal — money in is good news, not an emergency
139 sound: "cashregister",
140 buttons: link(payment.receipt_url, "View receipt"),
141 }
142}
Payload

The Square payment.updated webhook

This is what Square sends to your URL for payment.updated. It is a sample, trimmed to the fields recipes use.

payment.updated · sample.json
1{
2 "data": {
3 "id": "hYy9pRFVxpDsO1FB05SunFWUe9JZY",
4 "type": "payment",
5 "object": {
6 "payment": {
7 "id": "hYy9pRFVxpDsO1FB05SunFWUe9JZY",
8 "note": "Catering order #1042",
9 "status": "COMPLETED",
10 "order_id": "03O3USaPaAaFnI6kkwB1JxGgBsUZY",
11 "tip_money": {
12 "amount": 500,
13 "currency": "USD"
14 },
15 "created_at": "2026-09-28T14:16:51.086Z",
16 "updated_at": "2026-09-28T14:19:00.831Z",
17 "location_id": "S8GWD5R9QB376",
18 "receipt_url": "https://squareup.com/receipt/preview/hYy9pRFVxpDsO1FB05SunFWUe9JZY",
19 "source_type": "CARD",
20 "total_money": {
21 "amount": 4700,
22 "currency": "USD"
23 },
24 "amount_money": {
25 "amount": 4200,
26 "currency": "USD"
27 },
28 "card_details": {
29 "card": {
30 "bin": "540988",
31 "last_4": "9029",
32 "exp_year": 2029,
33 "card_type": "CREDIT",
34 "exp_month": 11,
35 "card_brand": "MASTERCARD",
36 "prepaid_type": "NOT_PREPAID"
37 },
38 "status": "CAPTURED",
39 "avs_status": "AVS_ACCEPTED",
40 "cvv_status": "CVV_ACCEPTED",
41 "entry_method": "KEYED",
42 "card_payment_timeline": {
43 "captured_at": "2026-09-28T14:19:00.832Z",
44 "authorized_at": "2026-09-28T14:16:51.198Z"
45 },
46 "statement_description": "SQ *EXAMPLE CAFE"
47 },
48 "version_token": "bhC3b8qKJvNDdxqKzXaeDsAjS1oMFuAKxGgT32HbE6S6o",
49 "approved_money": {
50 "amount": 4200,
51 "currency": "USD"
52 },
53 "receipt_number": "hYy9",
54 "buyer_email_address": "[email protected]"
55 }
56 }
57 },
58 "type": "payment.updated",
59 "event_id": "6a8f5f28-54a1-4eb0-a98a-3111513fd4fc",
60 "created_at": "2026-09-28T14:19:01.012Z",
61 "merchant_id": "6SSW7HV8K2ST5"
62}
FAQ

Square payment received notifications: questions

Does this work on iPhone and Android?

Yes. Install the JustPush app from the App Store or Google Play and sign in. Every phone signed in to your account gets the notification.

Do I need to write code?

No. Install the recipe in Studio, paste your webhook URL into Square and you are done. The code is there if you want to change the text, the sound or the buttons.

Can I change what the notification says?

Yes. After install the recipe's code is yours. Edit it in Studio and test it against the sample payload before you save.

What does it cost?

JustPush is free for 30 days. After that it's $19.99 a year, or $39.99 once. There is no extra charge for recipes.

Ready when you are

Square on your phone in two minutes.

Install the recipe, paste one URL, done. Free for 30 days, no credit card required.