Send handwritten cards for Shopify orders
Put a pen-written card in the box's wake: when a Shopify order is created, notecardHQ writes and mails a thank-you to the shipping address.
What you need
- A Shopify app or custom app with an
orders/createwebhook and its signing secret inSHOPIFY_WEBHOOK_SECRET. - A notecardHQ API key in
NOTECARDHQ_API_KEY.
The handler
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post("/webhooks/shopify/orders-create", express.raw({ type: "application/json" }), async (req, res) => {
const digest = crypto
.createHmac("sha256", process.env.SHOPIFY_WEBHOOK_SECRET)
.update(req.body)
.digest("base64");
const given = Buffer.from(req.get("X-Shopify-Hmac-Sha256") ?? "", "base64");
if (given.length !== 32 || !crypto.timingSafeEqual(given, Buffer.from(digest, "base64")))
return res.status(401).end();
const order = JSON.parse(req.body);
const s = order.shipping_address;
if (!s?.address1 || !s.first_name) return res.status(200).end(); // digital order, nothing to mail
const r = await fetch("https://you.notecardhq.com/api/v1/notes", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NOTECARDHQ_API_KEY}`,
"Content-Type": "application/json",
// One card per customer: later orders reuse the key and send nothing new.
"Idempotency-Key": `welcome:shopify:${order.customer?.id ?? order.id}`,
},
body: JSON.stringify({
externalId: String(order.customer?.id ?? order.id),
recipient: {
firstName: s.first_name, lastName: s.last_name ?? "",
businessName: s.company ?? "",
address1: s.address1, address2: s.address2 ?? "",
city: s.city, state: s.province_code ?? "", postalCode: s.zip ?? "",
country: s.country_code,
},
content: `Hi ${s.first_name},\n\nThank you for your first order with us. We hope you love it.\n\nThe team`,
}),
});
if (r.status === 429 || r.status >= 500) return res.status(503).end(); // Shopify retries
res.status(200).end();
});
app.listen(3000);
How "one card per customer" works
The Idempotency-Key is built from the Shopify customer id. The first order creates the note. A later order with the same key either returns that note or gets a 409 if the details changed, so the customer is never sent a second welcome card. To send a card on every order instead, use order:${order.id}.
Check the address first
US addresses are verified before a note is accepted. If the shipping address cannot be delivered, notecardHQ returns 422 and nothing is created. Log it and move on rather than retrying.
VIP and win-back cards
The same handler can send a card to your best customers, and a monthly list upload covers customers who stopped ordering. See handwritten thank-you notes for Shopify stores for the triggers, the Zapier route and what to write.
Field rules, statuses and errors are in the API reference. Prefer another language? See the quickstart.
Send your first note.
Tell us what you want to send and we will set up your workspace.