Handwritten notes API: send real pen-written cards from your code

Send real handwritten cards from your code with one POST per card. Learn idempotency keys, US address checks, note statuses, and how to test with a test key.

5 min read

A handwritten notes API lets your code send a real card, written by a robot holding a real pen, with one HTTP request per card. With notecardHQ, you POST the recipient and the exact note, and our studio in New York writes it on a 7x5 card, stamps it, and mails it. This guide covers how the request works, how to avoid sending a card twice, what happens to addresses, how to track status, and how to test when there is no sandbox.

One POST per card

Every card is one request to your workspace endpoint: POST https://<workspace>.notecardhq.com/api/v1/notes. You authenticate with a bearer key from the portal, and you send a JSON body with two required parts: the recipient and the content.

The recipient object takes firstName, lastName, businessName, address1, address2, city, state, postalCode, and country as an ISO-2 code like US or GB. The content field is the exact note, from 1 to 500 characters. What you send is what the pen writes. There is no template language to learn and no merge field to break.

You can also pass an optional context object. It is stored with the note and never written on the card. Use it for your own references: an order ID, a CRM record, the event that triggered the send.

curl -X POST https://<workspace>.notecardhq.com/api/v1/notes \
  -H "Authorization: Bearer $NOTECARD_KEY" \
  -H "Idempotency-Key: order-10482-thanks" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient": {
      "firstName": "Sam",
      "lastName": "Lee",
      "address1": "120 Main St",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97204",
      "country": "US"
    },
    "content": "Sam, thank you for your first order. We hope it is exactly what you wanted. Write back anytime.",
    "context": { "orderId": "10482" }
  }'

The response returns the note's id and its status. Store the id. It is how you look the card up later.

Idempotency keys: never send the same card twice

Networks fail. Workers retry. Queues deliver the same job more than once. With a paper card, a duplicate is not a harmless extra row in a database. It is a second envelope in someone's mailbox. That is why every request carries an Idempotency-Key header.

The rules are simple:

  • Same key and same body: you get back the same note. No second card is written.
  • Same key and a different body: the request is rejected with a 409, so a bug cannot quietly turn one card into two different ones.
  • New key: a new note.

Build the key from something stable in your own system, such as the order ID plus the reason for the card. Avoid random values generated at send time, because a retry would generate a new one and defeat the point. If your job runs twice for the same order, it should produce the same key both times.

Treat a 409 as a signal, not noise. It means two parts of your system disagree about what one card should say. Find out which one is right before you send anything else.

Address verification before anything is created

US addresses are verified and standardized when you submit them. If a US address is undeliverable, the request is rejected with a 422 and nothing is created. No card is written for an address that could never receive it, and you find out at request time instead of never.

Treat a 422 as a data problem, not a transient error. Do not retry it. Log it, surface it to whoever owns the customer record, and fix the address at the source.

International addresses are stored as sent. Cards are mailed internationally, but those addresses are not standardized, so format them the way the destination country expects and double check the country code.

Tracking status

Call GET /api/v1/notes/{id} to see where a card is. A note starts as created when it is accepted. It moves to card_printed once the pen robot has written it, and to card_dispatched once it has been stamped and sent. A note that will not be sent shows cancelled.

You can use these statuses to keep your own systems in sync: mark a CRM record when a card goes out, or show a teammate which customers have a card on the way. The same activity is visible in the portal, so people outside engineering can see every note without asking anyone to run a query.

Testing without a sandbox

A live key mails a real card on every accepted request, so test in two steps.

First, build against a test key. It runs the same validation as live, but notes are never written, mailed or billed; they move to printed and mailed a minute apart and fire the same signed webhooks, so you can test your whole flow. Assert on the request your code builds: the recipient fields, the content, the idempotency key, and how you handle a 409 and a 422. Most integration bugs live here, and none of them need a real card to find.

Then send one real note to yourself with your live key. Check the card when it arrives. Read it the way your customer will. Is the note the right length for the card? Does the name look right in handwriting? Is the return address the one you set in the portal?

Only after that should you wire the call to a live event. For ideas on which events deserve a card, see when to send handwritten thank you cards to customers.

What the pen can write

The content is written exactly as sent, so every character has to be writable. Letters, digits, and common punctuation are fine. Characters the handwriting model cannot write natively, like @, $, &, and %, are drawn as single-stroke glyphs. Emoji cannot be written, so strip them in your code.

Before any card is written, the note is turned into pen strokes and read back by OCR word by word. Any word that does not read back correctly is redrawn, and digits must read exactly. The full process is in how we check every card, and the writing side is in how to write a handwritten note for customers.

Design and return address

Cards are 7x5 inches. You upload your own front and back design in the card studio in the portal and set your return address there. API keys and billing live in the portal too. Your code only has to send the recipient and the words.

The full request and response reference is in the notecardHQ API docs.