How to schedule handwritten cards for birthdays and anniversaries

Keep birthdays and anniversaries in your CRM and send each handwritten card ahead of time with a sendOn date. notecardHQ holds it and mails it on that day. Timing, code, CSV and gotchas.

7 min read

To schedule handwritten cards for birthdays and anniversaries, keep the dates in your CRM, and send each card to notecardHQ ahead of time with a sendOn date. That date is the day the card is mailed. notecardHQ holds the card as scheduled, releases it to the robots two business days before, and mails it on that date. You do not need a scheduler that wakes up on the right morning. A job that runs once a week, or a spreadsheet uploaded once a month, is enough. Scheduled sends are available to API workspaces, by API and in the portal.

How sendOn works

  • Format. A calendar date as "YYYY-MM-DD", read in your workspace's time zone.
  • Range. Up to 365 days ahead. Today or an earlier date means "send now", exactly as if you had left it out. A later or malformed date is refused with a 422, and nothing is created.
  • Checked at once. A scheduled card is validated when you send it, just like a card sent now: the address is verified, the characters are checked and the 500-character limit applies. Problems surface the day you schedule it, not the day it is due.
  • Held until release. The note has the status scheduled. Two business days before its date it joins the normal flow, is written with a real pen, read back by OCR and mailed on the date.
  • Editable until then. In the portal you can edit the message, pick a new date or cancel a scheduled card until it is released.
  • Billed when it goes. Nothing is charged while a card waits. It is priced and billed when it is released and mailed.

Pick the mail date, not the birthday

sendOn is the day the card goes into the mail, not the day it arrives. Mail within the US usually takes a few days, so set sendOn about a week before the birthday or anniversary, and earlier for international addresses. A birthday card that arrives two days early reads as thoughtful. One that arrives two days late reads as an afterthought.

Keep the dates in your CRM

The date belongs on the contact record, next to the name and address, so it is kept up to date by the people who already maintain that record. Then pick one of two ways to turn it into scheduled cards.

Option 1: a weekly job

Once a week, a job reads the contacts whose birthday falls in the coming weeks and sends each card with its sendOn. The Idempotency-Key includes the year, so running the job again, or running it every day, never schedules a second card for the same birthday.

const DAY = 86400000;
const LEAD_DAYS = 7; // mail a week before the date
const iso = (d) => d.toISOString().slice(0, 10);

// The next birthday on or after `from`. Feb 29 falls on Feb 28 in other years.
function nextBirthday(month, day, from) {
  for (const year of [from.getUTCFullYear(), from.getUTCFullYear() + 1]) {
    const leap = new Date(Date.UTC(year, 1, 29)).getUTCMonth() === 1;
    const d = month === 2 && day === 29 && leap === false ? 28 : day;
    const date = new Date(Date.UTC(year, month - 1, d));
    if (date >= from) return date;
  }
}

const today = new Date(iso(new Date()) + "T00:00:00Z");

for (const c of contacts) { // from your CRM: id, name, address, birth month and day
  const birthday = nextBirthday(c.birthMonth, c.birthDay, new Date(today.getTime() + LEAD_DAYS * DAY));
  const sendOn = new Date(birthday.getTime() - LEAD_DAYS * DAY);
  if (sendOn - today > 42 * DAY) continue; // schedule six weeks ahead

  const res = 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 contact per birthday, however often this job runs.
      "Idempotency-Key": `birthday:${birthday.getUTCFullYear()}:${c.id}`,
    },
    body: JSON.stringify({
      externalId: c.id,
      recipient: {
        firstName: c.firstName, lastName: c.lastName,
        address1: c.address1, city: c.city, state: c.state,
        postalCode: c.postalCode, country: c.country,
      },
      content: `Hi ${c.firstName},\n\nHappy birthday. I hope the year ahead is a great one.\n\nMorgan`,
      sendOn: iso(sendOn),
      context: { trigger: "birthday", date: iso(birthday) },
    }),
  });
  if (res.status === 409) console.warn("contact changed after scheduling", c.id);
}

Three details in that code matter:

  • The key carries the year. birthday:2027:c_123 is a different card from birthday:2026:c_123, and the same card however many times the job sees it.
  • A 409 means the record changed. If the address or message differs from the card already scheduled under that key, notecardHQ refuses the new body rather than sending twice. Edit the scheduled card in the portal, or cancel it and send again under a new key.
  • context records why. It is stored with the note and never written on the card, so anyone looking at the note later can see what triggered it.

Run it from wherever your contacts live: a cron job in your backend, a scheduled automation in your CRM, or a scheduled Zap. The HubSpot and Salesforce recipes show how to call the API from each CRM; add sendOn to the body they send. Build the job with a test key first, since test notes are never written, mailed or billed.

Option 2: a monthly spreadsheet

No code at all: once a month, export next month's birthdays and anniversaries from your CRM with names, addresses and a sendOn column, and upload the file to Send to a list in the portal. Every row is checked with the same rules as the API, rows with problems are listed with the reason, and you see the price before you confirm. A note template such as Hi {{firstName}}, happy birthday. fills in each card, and the cards wait as scheduled until their dates. Schedule a year of client anniversaries in one upload if you like.

Anniversaries worth a card

  • Customer anniversaries. A year since the first order or the first contract. The date is already in your billing system or CRM. See milestone cards.
  • Home purchase anniversaries. For agents and lenders, the closing date. See real estate.
  • Policy and account anniversaries. For advisors and insurance agents, alongside client birthdays. See advisors and insurance.
  • Wedding anniversaries. For wedding vendors, the first anniversary is the card couples remember. See handwritten notes for wedding and event vendors.
  • Before a renewal. Not a celebration, but the same mechanics: a card scheduled 30 to 60 days before the renewal date.

What to write

Birthday cards are short. One line of greeting, one line that shows you know them, a name. The message is written exactly as sent, up to 500 characters.

  • Client birthday: "Hi Dana, happy birthday. I hope this year brings more of those trips you keep telling me about. Morgan"
  • Customer anniversary: "Hi Sam, it has been a year since you placed your first order with us. Thank you for sticking with a small team. Priya"
  • Home anniversary: "Hi Jordan and Sam, happy one year in the new place. I hope it already feels like home. Alex"

Write the note so it still makes sense whichever day it lands: "happy birthday" works a few days early, "today is your day" does not. Stock designs such as Happy Birthday and Cheers are ready to use, and the free handwriting preview shows your words in the robot's hand. More on copy in how to write a handwritten note for customers.

Gotchas

  • Time zone. sendOn is read in the workspace's time zone. Work out dates in that zone, not in UTC late at night.
  • February 29. A date that does not exist is refused, so pick February 28 or March 1 in other years, as the code above does.
  • People move. A card scheduled months ahead uses the address it was sent with. Scheduling a few weeks out, as above, keeps addresses current.
  • Holidays. The two-business-day release counts Monday to Friday and does not skip public holidays. Around holidays, add a day or two of lead time.
  • Opt-outs. Check contact preferences when the job runs, and cancel scheduled cards for anyone who opts out.

What it costs

Scheduled cards cost the same as any other card, all-in with postage: $3.25 each in the US at up to 499 a month, $2.95 from 500, $2.35 from 2,500 and $1.95 from 10,000. A scheduled card counts toward the month in which it is mailed. See pricing.

Start free with a test key, schedule next month's birthdays, and let the dates do the remembering.