Send a handwritten card in one request.

Every example below sends the same note. Swap in your workspace URL and key, and use a test key while you build: a live key mails a real card on every accepted request.

1. Get a key

Your workspace lives at https://<you>.notecardhq.com. Create a key under Integrations in the portal and keep it server side. No workspace yet? Sign up free: you get a test key straight away.

2. Send the note

curl

curl -X POST https://you.notecardhq.com/api/v1/notes \
  -H "Authorization: Bearer $NOTECARDHQ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: welcome:usr_8213" \
  -d '{
    "externalId": "usr_8213",
    "recipient": {
      "firstName": "Sam", "lastName": "Lee",
      "address1": "123 Main St", "city": "Austin",
      "state": "TX", "postalCode": "78701", "country": "US"
    },
    "content": "Hi Sam,\n\nWelcome aboard! We are glad you are here.\n\nThe team"
  }'

Node.js (18+)

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",
    "Idempotency-Key": "welcome:usr_8213",
  },
  body: JSON.stringify({
    externalId: "usr_8213",
    recipient: {
      firstName: "Sam", lastName: "Lee",
      address1: "123 Main St", city: "Austin",
      state: "TX", postalCode: "78701", country: "US",
    },
    content: "Hi Sam,\n\nWelcome aboard! We are glad you are here.\n\nThe team",
  }),
});
const note = await res.json();
if (!res.ok) throw new Error(note.error);
console.log(note.id, note.status); // "created"

Python

import os, requests

res = requests.post(
    "https://you.notecardhq.com/api/v1/notes",
    headers={
        "Authorization": f"Bearer {os.environ['NOTECARDHQ_API_KEY']}",
        "Idempotency-Key": "welcome:usr_8213",
    },
    json={
        "externalId": "usr_8213",
        "recipient": {
            "firstName": "Sam", "lastName": "Lee",
            "address1": "123 Main St", "city": "Austin",
            "state": "TX", "postalCode": "78701", "country": "US",
        },
        "content": "Hi Sam,\n\nWelcome aboard! We are glad you are here.\n\nThe team",
    },
    timeout=30,
)
note = res.json()
res.raise_for_status()
print(note["id"], note["status"])

PHP

$ch = curl_init("https://you.notecardhq.com/api/v1/notes");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("NOTECARDHQ_API_KEY"),
        "Content-Type: application/json",
        "Idempotency-Key: welcome:usr_8213",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "externalId" => "usr_8213",
        "recipient" => [
            "firstName" => "Sam", "lastName" => "Lee",
            "address1" => "123 Main St", "city" => "Austin",
            "state" => "TX", "postalCode" => "78701", "country" => "US",
        ],
        "content" => "Hi Sam,\n\nWelcome aboard! We are glad you are here.\n\nThe team",
    ]),
]);
$note = json_decode(curl_exec($ch), true);
echo $note["id"] . " " . $note["status"];

3. Read its status

curl https://you.notecardhq.com/api/v1/notes/NOTE_ID \
  -H "Authorization: Bearer $NOTECARDHQ_API_KEY"

A note moves from created to card_printed (written) to card_dispatched (mailed). A note you cancel in the portal before it is written shows cancelled.

What to handle

  • Retries. On a network error, a 429 or a 5xx, retry with the same Idempotency-Key and the same body. You get the original note back, never a second card.
  • 409. The key was already used with a different body. Stop and check; never mint a new key to get past it.
  • 422. A field, an unwritable character or an undeliverable US address. The error says which, and nothing was created.

Next: wire it to an event with the Stripe, Shopify, HubSpot, Salesforce or Zapier recipe, see every integration, or read the full API reference.

Get your API key.

Tell us what you want to send and we will set up your workspace and key.