NAV Navbar
shell javascript

Introduction

API Endpoint:

https://api.handwrite.io/v1/

Welcome to the Handwrite API!

You can use our API to send handwritten notes in an automated manner, using our REST endpoints.

We have language bindings in Shell and JavaScript, with Python and Ruby coming soon!

If you have questions or feedback please feel free to reach out to us here.

Getting Started

Handwrite uses API keys to allow access to the API. You must first sign up for a Handwrite account to obtain an API key. Sign up here. You will be charged per card based on the plan you choose.

Once you're logged in, you can create a key by going to the developer dashboard.

You'll notice when you create a key that it will start with test_hw or live_hw. Test keys will not count against your usage and can be used for testing purposes as you might have guessed!

An API key is expected to be included in all API requests to the server in a header that looks like the following:

Authorization: live_hw_sid92ldkasiie299dkw

Also, the content type must be Content-Type: application/json

Endpoints

Get Handwritings

The Request

curl --request GET \
  --url https://api.handwrite.io/v1/handwriting \
  --header 'authorization: test_hw_54838bde67e8e6255fa6' \
  --header 'content-type: application/json'
const request = require("request");

const options = {
  method: "GET",
  url: "https://api.handwrite.io/v1/handwriting",
  headers: {
    "content-type": "application/json",
    authorization: "test_hw_54838bde67e8e6255fa6"
  }
};

request(options, (error, response, body) => {
  if (error) throw new Error(error);

  console.log(body);
});

The Response - An array of handwriting objects in JSON format

[
  {
    "_id": "5db6f0724cc1751452c5ae8e",
    "name": "Jeremy",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270190/cards/wkwtnagsty79e0tlbiad.jpg"
  },
  {
    "_id": "5db6f08c4cc1751452c5ae8f",
    "name": "Tribeca",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270217/cards/hs92dvha3i5bvuhnboz7.jpg"
  },
  {
    "_id": "5db6f0f14cc1751452c5ae90",
    "name": "Terry",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270316/cards/bjocrcfhed6dwdadbtpv.jpg"
  }
]

This will fetch handwriting options for your users to preview and choose from.

Handwriting examples

HTTP Request

POST https://api.handwrite.io/v1/handwriting

Get Stationery

The Request

curl --request GET \
  --url https://api.handwrite.io/v1/stationery \
  --header 'authorization: test_hw_54838bde67e8e6255fa6' \
  --header 'content-type: application/json'
const request = require("request");

const options = {
  method: "GET",
  url: "https://api.handwrite.io/v1/stationery",
  headers: {
    "content-type": "application/json",
    authorization: "test_hw_54838bde67e8e6255fa6"
  }
};

request(options, (error, response, body) => {
  if (error) throw new Error(error);

  console.log(body);
});

The Response - An array of stationery objects in JSON format

[
  {
    "_id": "5db6f1854cc1751452c5ae93",
    "name": "Classic White",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270464/cards/yflijfai9wm38czthluk.jpg"
  },
  {
    "_id": "5db6f19b4cc1751452c5ae95",
    "name": "Classic Navy",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270484/cards/afwlmwfs4dkh5s6xt5uc.jpg"
  },
  {
    "_id": "5db6f1b74cc1751452c5ae96",
    "name": "Hello",
    "preview_url": "http://res.cloudinary.com/handwrite/image/upload/v1572270512/cards/mb9fhgwgnkdxiqtr9k0i.jpg"
  }
]

This will fetch any custom stationery you have uploaded as well as the publicly available options we provide.

Stationery examples

HTTP Request

GET https://api.handwrite.io/v1/stationery

Send a Letter

The Request

curl --request POST \
  --url https://api.handwrite.io/v1/send \
  --header 'authorization: test_hw_54838bde67e8e6255fa6' \
  --header 'content-type: application/json' \
  --data '{
  "message": "Hey dude,\nIt was great meeting you last week at the party. We'\''d love to have you back at the next one!\n\nBest,\n-Jackie",
  "handwriting": "5db6f0724cc1751452c5ae8e",
  "card": "5db6f0724cc1751452c5ae8e",
  "recipients": [
    {
      "firstName": "The",
      "lastName": "Dude",
      "company": "Unemployed",
      "street1": "25 Main Street",
      "city": "Los Angeles",
      "state": "CA",
      "zip": "90210"
    }
  ],
  "from": {
    "firstName": "Jackie",
    "lastName": "Treehorn",
    "street1": "1 Random Street",
    "street2": "Apt 33A",
    "city": "Malibu",
    "state": "CA",
    "zip": "90263"
  }
}'
const request = require("request");

const options = {
  method: "POST",
  url: "https://api.handwrite.io/v1/send",
  headers: {
    "content-type": "application/json",
    authorization: "test_hw_54838bde67e8e6255fa6"
  },
  body: {
    message:
      "Hey dude,\nIt was great meeting you last week at the party. We'd love to have you back at the next one!\n\nBest,\n-Jackie",
    handwriting: "5db6f0724cc1751452c5ae8e",
    card: "5db6f0724cc1751452c5ae8e",
    recipients: [
      {
        firstName: "The",
        lastName: "Dude",
        company: "Unemployed",
        street1: "25 Main Street",
        city: "Los Angeles",
        state: "CA",
        zip: "90210"
      }
    ],
    from: {
      firstName: "Jackie",
      lastName: "Treehorn",
      street1: "1 Random Street",
      street2: "Apt 33A",
      city: "Malibu",
      state: "CA",
      zip: "90263"
    }
  },
  json: true
};

request(options, (error, response, body) => {
  if (error) throw new Error(error);

  console.log(body);
});

The Response - An array of orders in JSON format

[
  {
    "_id": "5dba45e8f2b173cb5dff0300",
    "message": "Hey dude,\nIt was great meeting you last week at the party. We'd love to have you back at the next one!\n\nBest,\n-Jackie",
    "to": {
      "firstName": "The",
      "lastName": "Dude",
      "company": "Unemployed",
      "street1": "25 Main Street",
      "city": "Los Angeles",
      "state": "CA",
      "zip": "90210"
    },
    "from": {
      "firstName": "Jackie",
      "lastName": "Treehorn",
      "street1": "1 Random Street",
      "street2": "Apt 33A",
      "city": "Malibu",
      "state": "CA",
      "zip": "90263"
    },
    "status": "processing",
    "handwriting": "5db6f0724cc1751452c5ae8e",
    "card": "5db6f0724cc1751452c5ae8e",
    "createdAt": "2019-10-31T02:24:40.648Z"
  }
]

Send a letter to between 1 and 1000 recipients at once. For higher limits, contact us.

HTTP Request

POST https://api.handwrite.io/v1/send

Request parameters

Parameter Type Description
message required String This is the body of the letter. Maximum of 320 characters.
card required String ID of the stationery/card you want. This will also determine whether it is the front or back of card.
handwriting required String ID of the handwriting you want to use.
recipients required Array List of recipient objects. Must have at least one, but can be up to 1000.
recipients[n].firstName String Recipient first name
recipients[n].lastName String Recipient last name
recipients[n].company String Recipient company. If this is included, company will be on the first line, with attention to on the second
recipients[n].street1 required String First line of the address, e.g. 555 Terrance Street
recipients[n].street2 String Second line of the address, e.g. Apt. 201
recipients[n].city required String
recipients[n].state required String *Must be the capitalized two digit abbreviation, e.g. AL instead of Alabama
recipients[n].zip required String Must be exactly 5 characters
from Object Return address. (optional)
from.firstName String
from.lastName String
from.street1 String
from.street2 String
from.city String
from.state String
from.zip String

Merge Variables

Sometimes you'll want to send a card to many people with slightly different text on each one. For example, you might want to address each recipient by his or her first name.

In order to do this, you'll use "merge variables."

Hey {firstName}, I hope all is well down in {city}! How's business at {company} these days?

In this case, each occurrence of {firstName} will be replaced with the recipient's actual first name.

We support the following merge variables currently, with more coming in the future including custom merge variables:

Rate Limiting

The Handwrite API is rate limited to prevent abuse that would degrade our ability to maintain consistent API performance for all users.

By default, each API key is rate limited at 60 requests per minute. If your requests are being rate limited, HTTP response code 429 will be returned with an rate_limit_exceeded error.

In your response headers, you should see information pertaining to your limits at any given time.

Header Description
X-RateLimit-Limit The maximum number of requests that the consumer is permitted to make per minute.
X-RateLimit-Remaining The number of requests remaining in the current rate limit window.
X-RateLimit-Reset The time at which the current rate limit window resets.

Response Codes

Handwrite uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted or was the incorrect type, etc.). Codes in the 5xx range indicate an error with our servers.

The Handwrite API uses the following response codes:

Error Code Meaning
200 Success. Everything worked as expected
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
404 Not Found -- The specified resource could not be found.
429 Too Many Requests -- You're requesting too much! Slow down!
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.