postgrid-node-client

Node.js Client for PostGrid Business API


Keywords
postgrid.com, postal delivery, api
License
MIT
Install
npm install postgrid-node-client@0.4.0

Documentation

postgrid-node-client

postgrid-node-client is a Node/JS and TypeScript Client for PostGrid that allows you to use normal Node syntax to send PDFs, and other documents, through Postal Delivery to recipients. PostGrid has a set of REST endpoints but this affords some nice convenience features for the Node developer.

Install

# with npm
$ npm install postgrid-node-client

Usage

This README isn't going to cover all the specifics of what PostGrid is, and how to use it - it's targeted as a companion to the PostGrid developer docs that explain each of the endpoints and how the general PostGrid workflow works.

However, we'll put in plenty of examples so that it's clear how to use this library to interact with PostGrid.

Getting your API Key

As documented on the PostGrid site, the first step is getting an API Key for the calls to PostGrid. This is available on their Dashboard page, once you login. For the rest of this document, the API Key will be seen as: [Your API Key], and will need to be replaced with the API Key you obtain from the site.

Creating the Client

All PostGrid functions are available from the client, and the basic construction of the client is:

import { PostGrid } from 'postgrid-node-client'
const client = new PostGrid('[Your API Key]')

If you'd like to provide the webhook URL in the constructor, you can do that with:

const client = new PostGrid(
  '[Your API Key]',
  {
    webhookUrl: 'https://my.service.com/postgrid/callback',
    webhookSecret: 'abc123456the-tall-brown-bear',
    webhookEvents: ['letter.created', 'letter.updated'],
  }
)

where the options can include:

  • webhookUrl - the URL for all PostGrid updates to be sent
  • webhookSecret - the JWT encryption secret for the payload on the webhook so that it's safe in transmission back to the service.
  • webhookEvents - the array of strings that are the events that this webhook is expected to receive from PostGrid.

Contact Calls

In general, the Contacts are the contact information for a Sender or Recipient in the PostGrid system. These can be created, updated, and deleted, as individual entities, or they can be created as a part of a more complex operation - such as Create a Letter.

Create Contact

const contact = await client.contact.create({
  addressLine1: '2929 Eagledale Dr',
  provinceOrState: 'IN',
  postalOrZip: '46224',
  countryCode: 'US',
  firstName: 'Jim',
  lastName: 'Harrison',
  email: 'jim@jimmys.com',
  phoneNumber: '317-555-1212',
  companyName: 'Jimmys Bar',
  jobTitle: 'Barkeep',
})

This will create the contact with the provided address and contact information, and in the event that the details are the same as an existing Contact, this will not create a new Contact, but simply return the existing one with the same data. The response will be something like:

{
  "success": true,
  "contact": {
    "id": "contact_igdxsBys7TPJYf47PevBJj",
    "object": "contact",
    "live": false,
    "addressLine1": "2929 EAGLEDALE DR",
    "addressLine2": null,
    "addressStatus": "verified",
    "city": null,
    "companyName": "Jimmys Bar",
    "country": "UNITED STATES",
    "countryCode": "US",
    "email": "jim@jimmys.com",
    "firstName": "Jim",
    "jobTitle": "Barkeep",
    "lastName": "Harrison",
    "phoneNumber": "317-555-1212",
    "postalOrZip": "46224",
    "provinceOrState": "IN",
    "createdAt": "2021-07-15T18:36:45.348Z",
    "updatedAt": "2021-07-15T18:36:45.348Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

So looking at the success value of the response will quickly let you know the outcome of the call.

Get a Contact

const doc = await client.contact.get(id)

where id is the Contact ID, like contact_igdxsBys7TPJYf47PevBJj, in the above example, and the response will be something like the response to the client.contact.create() function.

List Contacts

const doc = await client.contacts.list()

This will list all the Contacts assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "contacts": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 12,
    "data": [
      {
        "id": "contact_2rWLmfNFPKQLtZEy72qT8e",
        "object": "contact",
        "live": false,
        "addressLine1": "2929 EAGLEDALE DR",
        "addressLine2": null,
        "addressStatus": "verified",
        "city": null,
        "companyName": "Jimmys Bar",
        "country": "UNITED STATES",
        "countryCode": "US",
        "email": "jim@jimmys.com",
        "firstName": "Jim",
        "jobTitle": "Barkeep",
        "lastName": "Harrison",
        "phoneNumber": "317-555-1212",
        "postalOrZip": "46224",
        "provinceOrState": "IN",
        "createdAt": "2021-07-15T18:54:44.521Z",
        "updatedAt": "2021-07-15T18:54:44.521Z"
      },
      ...
    ]
  }
}

Delete a Contact

const doc = await client.contact.delete(id)

where id is the Contact ID, like contact_igdxsBys7TPJYf47PevBJj, in the above example, and the response will be something like:

{
  "success": true,
  "contact": {
    "id": "contact_2gA88Z5Mb3jtB1nnpQCCAn",
    "object": "contact",
    "deleted": true
  }
}

Letter Calls

The PostGrid Letter is a basic Page Document that can be sourced from an HTML template, with replacable parameters, or a PDF, and can be sent from a Sender to a Recipient through the Postal System.

Create Letter

The basic Create Letter call looks something like this:

const letter = await client.letter.create({
  description: 'Cool new letter',
  pdf: 'https://www.icnaam.org/documents/8x11singlesample.pdf',
  to: {
    firstName: 'Steve',
    lastName: 'Smith',
    companyName: 'Acme Rentals',
    addressLine1: '5454 West 34th Street',
    city: 'Indianapolis',
    provinceOrState: 'IN',
    postalOrZip: '46224',
    countryCode: 'US',
  },
  from: {
    firstName: 'John',
    lastName: 'Quincy',
    companyName: 'US Steel',
    addressLine1: '123 Main Street',
    city: 'Atlanta',
    provinceOrState: 'GA',
    postalOrZip: '12345',
    countryCode: 'US',
  },
})

This will create the letter with the provided addresses, and in it will then start it's journey to the recipient. The response will be something like:

{
  "success": true,
  "letter": {
    "id": "letter_hBy6M5DMKEqp7z1paW1TDM",
    "object": "letter",
    "live": false,
    "addressPlacement": "insert_blank_page",
    "color": false,
    "description": "Cool new letter",
    "doubleSided": false,
    "from": {
      "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
      "object": "contact",
      "addressLine1": "123 MAIN STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "ATLANTA",
      "companyName": "US Steel",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "John",
      "lastName": "Quincy",
      "postalOrZip": "12345",
      "provinceOrState": "GA"
    },
    "sendDate": "2021-07-15T19:51:50.356Z",
    "status": "ready",
    "to": {
      "id": "contact_f8NLBJXjV82HnM8emVow3r",
      "object": "contact",
      "addressLine1": "5454 WEST 34TH STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "INDIANAPOLIS",
      "companyName": "Acme Rentals",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "Steve",
      "lastName": "Smith",
      "postalOrZip": "46224",
      "provinceOrState": "IN"
    },
    "uploadedPdf": "https://pg-prod-bucket-1.s3.amazonaws.com/test/...",
    "createdAt": "2021-07-15T19:51:50.360Z",
    "updatedAt": "2021-07-15T19:51:50.360Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

It's important to remember that if the same Contact information is supplied as an existing Contact, PostGrid will not create a new Contact - simply reuse the one it already has.

But there are other ways to create a letter. You can use the Contact IDs, like:

const letter = await client.letter.create({
  description: 'Cool new letter',
  pdf: 'https://www.icnaam.org/documents/8x11singlesample.pdf',
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
})

so that if you know the created Contact data, you can just pass in the IDs. Of course, you can mix-and-match as well.

You can also use a standard Node Buffer to load up the Letter source:

import fs from 'fs'

const doc = fs.readFileSync('/my/local/file.pdf')

const letter = await client.letter.create({
  description: 'Cool new letter',
  pdf: doc,
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
})

all of these are covered in the different forms of the PostGrid Create Letter endpoints, but the Client detects the inputs and acts accordingly. You just have to provide the data.

Get a Letter

const doc = await client.letter.get(id)

where id is the Letter ID, like letter_hBy6M5DMKEqp7z1paW1TDM, in the above example, and the response will be something like the response to the client.letter.create() function.

List Letters

const doc = await client.letter.list()

This will list all the Letters assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "letters": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 27,
    "data": [
      {
        "id": "letter_3j3st1ZzZmFPv9bn1BnMeE",
        "object": "letter",
        "live": false,
        "addressPlacement": "insert_blank_page",
        "color": false,
        "description": "Cool new letter",
        "doubleSided": false,
        "from": {
          "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
          "object": "contact",
          "addressLine1": "123 MAIN STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "ATLANTA",
          "companyName": "US Steel",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "John",
          "lastName": "Quincy",
          "postalOrZip": "12345",
          "provinceOrState": "GA"
        },
        "sendDate": "2021-07-15T20:02:55.417Z",
        "status": "ready",
        "to": {
          "id": "contact_f8NLBJXjV82HnM8emVow3r",
          "object": "contact",
          "addressLine1": "5454 WEST 34TH STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "INDIANAPOLIS",
          "companyName": "Acme Rentals",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "Steve",
          "lastName": "Smith",
          "postalOrZip": "46224",
          "provinceOrState": "IN"
        },
        "uploadedPdf": "https://pg-prod-bucket-1.s3.amazonaws.com/test/...",
        "createdAt": "2021-07-15T20:02:55.421Z",
        "updatedAt": "2021-07-15T20:02:55.421Z"
      },
      ...
    ]
  }
}

Progress a Test Letter

This function will move a Test Letter through the server-side processing steps, one at a time to allow the caller to verify the webhook calls. This is only available for Test Letters.

const move = await client.letter.progress(id)

where id is the Letter ID, like letter_hBy6M5DMKEqp7z1paW1TDM, in the above example, and the response will be similar to the response from client.letter.get(id).

Delete a Letter

This function will delete - or Cancel a Letter that's not yet been sent.

const doc = await client.letter.delete(id)

where id is the Letter ID, like letter_hBy6M5DMKEqp7z1paW1TDM, in the above example, and the response will be something like:

{
  "success": true,
  "letter": {
    "id": "letter_hBy6M5DMKEqp7z1paW1TDM",
    "object": "letter",
    "deleted": true
  }
}

Postcard Calls

The PostGrid Postcard is a basic postcard that can be sourced from an HTML template, with replacable parameters, or a PDF, and can be sent from a Sender to a Recipient through the Postal System. The available sizes are:

  • 6x4
  • 9x6
  • 11x6

which is specified in the size parameter of the postcard.create() function call.

Create Postcard

The basic Create Postcard call looks something like this:

const postcard = await client.postcard.create({
  description: 'Cool new postcard',
  size: '6x4',
  frontHTML: 'Hello, {{to.firstName}}',
  backHTML: 'Hello again, {{to.firstName}}',
  to: {
    firstName: 'Steve',
    lastName: 'Smith',
    companyName: 'Acme Rentals',
    addressLine1: '5454 West 34th Street',
    city: 'Indianapolis',
    provinceOrState: 'IN',
    postalOrZip: '46224',
    countryCode: 'US',
  },
  from: {
    firstName: 'John',
    lastName: 'Quincy',
    companyName: 'US Steel',
    addressLine1: '123 Main Street',
    city: 'Atlanta',
    provinceOrState: 'GA',
    postalOrZip: '12345',
    countryCode: 'US',
  },
})

This will create the postcard with the provided addresses, and in it will then start it's journey to the recipient. The response will be something like:

{
  "success": true,
  "postcard": {
    "id": "postcard_48Fm3w14DGjRKKpsD2GrXJ",
    "object": "postcard",
    "live": false,
    "backHtml": "Hello again, {{to.firstName}}",
    "description": "Cool new postcard",
    "from": {
      "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
      "object": "contact",
      "addressLine1": "123 MAIN STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "ATLANTA",
      "companyName": "US Steel",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "John",
      "lastName": "Quincy",
      "postalOrZip": "12345",
      "provinceOrState": "GA"
    },
    "frontHtml": "Hello, {{to.firstName}}",
    "sendDate": "2021-07-16T14:09:38.286Z",
    "size": "6x4",
    "status": "ready",
    "to": {
      "id": "contact_f8NLBJXjV82HnM8emVow3r",
      "object": "contact",
      "addressLine1": "5454 WEST 34TH STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "INDIANAPOLIS",
      "companyName": "Acme Rentals",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "Steve",
      "lastName": "Smith",
      "postalOrZip": "46224",
      "provinceOrState": "IN"
    },
    "createdAt": "2021-07-16T14:09:38.290Z",
    "updatedAt": "2021-07-16T14:09:38.290Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

It's important to remember that if the same Contact information is supplied as an existing Contact, PostGrid will not create a new Contact - simply reuse the one it already has.

But there are other ways to create a postcard. You can use the Contact IDs, like:

const postcard = await client.postcard.create({
  description: 'Cool new postcard',
  pdf: 'https://my.artwork.com/postcards/6x4sample.pdf',
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
})

so that if you know the created Contact data, you can just pass in the IDs. Of course, you can mix-and-match as well.

You can also use a standard Node Buffer to load up the Letter source:

import fs from 'fs'

const doc = fs.readFileSync('/my/local/file.pdf')

const postcard = await client.postcard.create({
  description: 'Cool new postcard',
  pdf: doc,
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
})

all of these are covered in the different forms of the PostGrid Create Postcard endpoints, but the Client detects the inputs and acts accordingly. You just have to provide the data.

Get a Postcard

const doc = await client.postcard.get(id)

where id is the Postcard ID, like postcard_48Fm3w14DGjRKKpsD2GrXJ, in the above example, and the response will be something like the response to the client.postcard.create() function.

List Postcards

const doc = await client.postcard.list()

This will list all the Postcards assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "postcards": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 3,
    "data": [
      {
        "id": "postcard_agV7LbeDfRbdNUdnfePAyD",
        "object": "postcard",
        "live": false,
        "backHtml": "Hello again, {{to.firstName}}",
        "description": "Cool new postcard",
        "from": {
          "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
          "object": "contact",
          "addressLine1": "123 MAIN STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "ATLANTA",
          "companyName": "US Steel",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "John",
          "lastName": "Quincy",
          "postalOrZip": "12345",
          "provinceOrState": "GA"
        },
        "frontHtml": "Hello, {{to.firstName}}",
        "sendDate": "2021-07-16T14:14:37.023Z",
        "size": "6x4",
        "status": "ready",
        "to": {
          "id": "contact_f8NLBJXjV82HnM8emVow3r",
          "object": "contact",
          "addressLine1": "5454 WEST 34TH STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "INDIANAPOLIS",
          "companyName": "Acme Rentals",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "Steve",
          "lastName": "Smith",
          "postalOrZip": "46224",
          "provinceOrState": "IN"
        },
        "createdAt": "2021-07-16T14:14:37.027Z",
        "updatedAt": "2021-07-16T14:14:37.027Z"
      },
      {
        "id": "postcard_48Fm3w14DGjRKKpsD2GrXJ",
        "object": "postcard",
        "live": false,
        "backHtml": "Hello again, {{to.firstName}}",
        "description": "Cool new postcard",
        "from": {
          "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
          "object": "contact",
          "addressLine1": "123 MAIN STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "ATLANTA",
          "companyName": "US Steel",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "John",
          "lastName": "Quincy",
          "postalOrZip": "12345",
          "provinceOrState": "GA"
        },
        "frontHtml": "Hello, {{to.firstName}}",
        "pageCount": 2,
        "sendDate": "2021-07-16T14:09:38.286Z",
        "size": "6x4",
        "status": "cancelled",
        "to": {
          "id": "contact_f8NLBJXjV82HnM8emVow3r",
          "object": "contact",
          "addressLine1": "5454 WEST 34TH STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "INDIANAPOLIS",
          "companyName": "Acme Rentals",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "Steve",
          "lastName": "Smith",
          "postalOrZip": "46224",
          "provinceOrState": "IN"
        },
        "url": "https://pg-prod-bucket-1.s3.amazonaws.com/test/...",
        "createdAt": "2021-07-16T14:09:38.290Z",
        "updatedAt": "2021-07-16T14:09:42.691Z"
      },
      ...
    ]
  }
}

Progress a Test Postcard

This function will move a Test Postcard through the server-side processing steps, one at a time to allow the caller to verify the webhook calls. This is only available for Test Postcards.

const move = await client.postcard.progress(id)

where id is the Postcard ID, like postcard_agV7LbeDfRbdNUdnfePAyD, in the above example, and the response will be similar to the response from client.postcard.get(id).

Delete a Postcard

This function will delete - or Cancel a Postcard that's not yet been sent.

const doc = await client.postcard.delete(id)

where id is the Postcard ID, like postcard_agV7LbeDfRbdNUdnfePAyD, in the above example, and the response will be something like:

{
  "success": true,
  "postcard": {
    "id": "postcard_agV7LbeDfRbdNUdnfePAyD",
    "object": "postcard",
    "deleted": true
  }
}

Bank Account Calls

In general, the Bank Accounts are the account information for creating a check/cheque in the PostGrid system. These accounts can be created, updated, and deleted, as individual entities.

Create Bank Account

const account = await client.bankAccount.create({
  description: 'This is where to put your marshmallows',
  bankName: 'Bank of Marshmallows',
  bankPrimaryLine: '3288 Tara Lane',
  bankSecondaryLine: 'Indianapolis, IN',
  bankCountryCode: 'US',
  routingNumber: '123456789',
  accountNumber: '100010001001',
  signatureText: 'Stay Puff'
})

This will create the account with the provided address and account information. The response will be something like:

{
  "success": true,
  "account": {
    "id": "bank_gMpKxPyiGzt1ZwACTmLHHn",
    "object": "bank_account",
    "live": false,
    "accountNumberLast4": "1001",
    "bankCountryCode": "US",
    "bankName": "Bank of Marshmallows",
    "bankPrimaryLine": "3288 Tara Lane",
    "bankSecondaryLine": "Indianapolis, IN",
    "description": "This is where to put your marshmallows",
    "routingNumber": "123456789",
    "signatureText": "Stay Puff",
    "createdAt": "2021-07-18T16:19:35.626Z",
    "updatedAt": "2021-07-18T16:19:35.626Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

So looking at the success value of the response will quickly let you know the outcome of the call.

Get a Bank Account

const account = await client.bankAccount.get(id)

where id is the Bank Account ID, like bank_gMpKxPyiGzt1ZwACTmLHHn, in the above example, and the response will be something like the response to the client.bankAccount.create() function.

List Bank Accounts

const accts = await client.bankAccount.list()

This will list all the Bank Accounts assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "accounts": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 1,
    "data": [
      {
        "id": "bank_a2M4zstWGeYeJ8gbtVKKr5",
        "object": "bank_account",
        "live": false,
        "accountNumberLast4": "1001",
        "bankCountryCode": "US",
        "bankName": "Bank of Marshmallows",
        "bankPrimaryLine": "3288 Tara Lane",
        "bankSecondaryLine": "Indianapolis, IN",
        "description": "This is where to put your marshmallows",
        "routingNumber": "123456789",
        "signatureText": "Stay Puff",
        "createdAt": "2021-07-18T16:22:44.579Z",
        "updatedAt": "2021-07-18T16:22:44.579Z"
      }
    ]
  }
}

Delete a Bank Account

const drop = await client.bankAccount.delete(id)

where id is the Bank Account ID, like bank_a2M4zstWGeYeJ8gbtVKKr5, in the above example, and the response will be something like:

{
  "success": true,
  "account": {
    "id": "bank_a2M4zstWGeYeJ8gbtVKKr5",
    "object": "bank_account",
    "deleted": true
  }
}

Cheque/Check Calls

The PostGrid Cheque (Check) is a check written against a Bank Account that can be sent to the to recipient with an optional letter sourced from an in-line HTML blob, a Template, or a PDF, and will be sent from a Sender to a Recipient through the Postal System.

Create Check

The basic Create Check call looks something like this:

const check = await client.check.create({
  description: 'Cool new check',
  letterHTML: 'Hello {{to.firstName}}',
  to: {
    firstName: 'Steve',
    lastName: 'Smith',
    companyName: 'Acme Rentals',
    addressLine1: '5454 West 34th Street',
    city: 'Indianapolis',
    provinceOrState: 'IN',
    postalOrZip: '46224',
    countryCode: 'US',
  },
  from: {
    firstName: 'John',
    lastName: 'Quincy',
    companyName: 'US Steel',
    addressLine1: '123 Main Street',
    city: 'Atlanta',
    provinceOrState: 'GA',
    postalOrZip: '12345',
    countryCode: 'US',
  },
  bankAccount: 'bank_gMpKxPyiGzt1ZwACTmLHHn',
  amount: 10000,
  memo: 'Invoice 1233',
  number: 9667,
})

This will create the check with the provided addresses, against the Bank Account referenced by bank_gMpKxPyiGzt1ZwACTmLHHn, and will include a letter in the same envelope, with the contents of the letterHTML. The response will be something like:

{
  "success": true,
  "check": {
    "id": "cheque_7GrdUQPmbkAXJg8vLkJK9B",
    "object": "cheque",
    "live": false,
    "amount": 10000,
    "bankAccount": "bank_gMpKxPyiGzt1ZwACTmLHHn",
    "currencyCode": "USD",
    "description": "Cool new check",
    "from": {
      "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
      "object": "contact",
      "addressLine1": "123 MAIN STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "ATLANTA",
      "companyName": "US Steel",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "John",
      "lastName": "Quincy",
      "postalOrZip": "12345",
      "provinceOrState": "GA"
    },
    "letterHtml": "Hello {{to.firstName}}",
    "memo": "Invoice 1233",
    "number": 9667,
    "sendDate": "2021-07-19T09:57:28.214Z",
    "status": "ready",
    "to": {
      "id": "contact_f8NLBJXjV82HnM8emVow3r",
      "object": "contact",
      "addressLine1": "5454 WEST 34TH STREET",
      "addressLine2": null,
      "addressStatus": "verified",
      "city": "INDIANAPOLIS",
      "companyName": "Acme Rentals",
      "country": "UNITED STATES",
      "countryCode": "US",
      "firstName": "Steve",
      "lastName": "Smith",
      "postalOrZip": "46224",
      "provinceOrState": "IN"
    },
    "createdAt": "2021-07-19T09:57:28.220Z",
    "updatedAt": "2021-07-19T09:57:28.220Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

It's important to remember that if the same Contact information is supplied as an existing Contact, PostGrid will not create a new Contact - simply reuse the one it already has.

But there are other ways to create a check. You can use the Contact IDs, like:

const postcard = await client.postcard.create({
  description: 'Cool new check',
  letterHTML: 'Hello {{to.firstName}}',
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
  bankAccount: 'bank_gMpKxPyiGzt1ZwACTmLHHn',
  amount: 10000,
  memo: 'Invoice 1233',
  number: 9667,
})

so that if you know the created Contact data, you can just pass in the IDs. Of course, you can mix-and-match as well.

You can also use a standard Node Buffer to load up the letter source:

import fs from 'fs'

const doc = fs.readFileSync('/my/local/file.pdf')

const postcard = await client.postcard.create({
  description: 'Cool new check',
  letterPDF: doc,
  to: 'contact_f8NLBJXjV82HnM8emVow3r',
  from: 'contact_fo3HwdeFZ3wwNuHFAgszHt',
  bankAccount: 'bank_gMpKxPyiGzt1ZwACTmLHHn',
  amount: 10000,
  memo: 'Invoice 1233',
  number: 9667,
})

all of these are covered in the different forms of the PostGrid Create Cheque endpoints, but the Client detects the inputs and acts accordingly. You just have to provide the data.

Get a Check

const check = await client.check.get(id)

where id is the Postcard ID, like cheque_7GrdUQPmbkAXJg8vLkJK9B, in the above example, and the response will be something like the response to the client.check.create() function.

List Checks

const checks = await client.check.list()

This will list all the Cheques/Checks assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "checks": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 3,
    "data": [
      {
        "id": "cheque_1rLks7fM6nSC1jNpidv1fg",
        "object": "cheque",
        "live": false,
        "amount": 10000,
        "bankAccount": "bank_gMpKxPyiGzt1ZwACTmLHHn",
        "currencyCode": "USD",
        "description": "Cool new check",
        "from": {
          "id": "contact_fo3HwdeFZ3wwNuHFAgszHt",
          "object": "contact",
          "addressLine1": "123 MAIN STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "ATLANTA",
          "companyName": "US Steel",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "John",
          "lastName": "Quincy",
          "postalOrZip": "12345",
          "provinceOrState": "GA"
        },
        "letterHtml": "Hello {{to.firstName}}",
        "memo": "Invoice 1233",
        "number": 9667,
        "sendDate": "2021-07-19T10:02:28.324Z",
        "status": "ready",
        "to": {
          "id": "contact_f8NLBJXjV82HnM8emVow3r",
          "object": "contact",
          "addressLine1": "5454 WEST 34TH STREET",
          "addressLine2": null,
          "addressStatus": "verified",
          "city": "INDIANAPOLIS",
          "companyName": "Acme Rentals",
          "country": "UNITED STATES",
          "countryCode": "US",
          "firstName": "Steve",
          "lastName": "Smith",
          "postalOrZip": "46224",
          "provinceOrState": "IN"
        },
        "createdAt": "2021-07-19T10:02:28.327Z",
        "updatedAt": "2021-07-19T10:02:28.327Z"
      },
      ...
    ]
  }
}

Progress a Test Cheque/Check

This function will move a Test Cheque/Check through the server-side processing steps, one at a time to allow the caller to verify the webhook calls. This is only available for Test Cheques/Checks.

const move = await client.check.progress(id)

where id is the Cheque ID, like cheque_7GrdUQPmbkAXJg8vLkJK9B, in the above example, and the response will be similar to the response from client.check.get(id).

Delete a Check

This function will delete - or Cancel a Cheque/Check that's not yet been sent.

const drop = await client.check.delete(id)

where id is the Postcard ID, like cheque_7GrdUQPmbkAXJg8vLkJK9B, in the above example, and the response will be something like:

{
  "success": true,
  "check": {
    "id": "cheque_7GrdUQPmbkAXJg8vLkJK9B",
    "object": "cheque",
    "deleted": true
  }
}

Webhook Calls

The PostGrid Webhook is documented on this page and is the traditional way for an scynchronous service to alert the client that something has changed.

Create Webhook

The basic Create Webhook call looks something like this:

const letter = await client.webhook.create({
  description: 'Cool new webhook',
  url: 'https://my.service.com/postgrid/callback',
  enabledEvents: ['letter.created'],
})

This will create the webhook back to the provided url, and will then be the notification system for any updates for the enabled events. The response will be something like:

{
  "success": true,
  "webhook": {
    "id": "webhook_wb6AAoBMcm1CNwWH3mkbr1",
    "object": "webhook",
    "live": false,
    "description": "Cool new webhook",
    "enabled": true,
    "enabledEvents": [
      "letter.created"
    ],
    "secret": "webhook_secret_uAMxoCjLyHoCFWoA6XvhdC",
    "url": "https://my.service.com/postgrid/callback",
    "createdAt": "2021-07-15T20:11:51.032Z",
    "updatedAt": "2021-07-15T20:11:51.032Z"
  }
}

If there had been an error, the response would be:

{
  "success": false,
  "error": {
    "type": "PostGrid_type",
    "message": "(Error message from PostGrid...)"
  }
}

Get a Webhook

const doc = await client.webhook.get(id)

where id is the Letter ID, like webhook_wb6AAoBMcm1CNwWH3mkbr1, in the above example, and the response will be something like the response to the client.webhook.create() function.

List Webhooks

const doc = await client.webhook.list()

This will list all the Webhooks assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "webhooks": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 1,
    "data": [
      {
        "id": "webhook_rqjK6m3T71butzwSd7zU4N",
        "object": "webhook",
        "live": false,
        "description": "Cool new webhook",
        "enabled": true,
        "enabledEvents": [
          "letter.created"
        ],
        "secret": "webhook_secret_ve1xLLrBWRfDhjhNZZMRn3",
        "url": "https://my.service.com/postgrid/callback",
        "createdAt": "2021-07-15T20:14:11.060Z",
        "updatedAt": "2021-07-15T20:14:11.060Z"
      }
    ]
  }
}

List Webhook Invocations

const doc = await client.webhook.invocations(id)

where id is the Webhook ID, like webhook_rqjK6m3T71butzwSd7zU4N, in the above example. This will list all the Webhooks assoiated with this API Key, and will do so in the PostGrid List paging scheme of limit and skip. These parameters are optional, and if they are omitted, the defaults are:

  • skip is 0
  • limit is 40

The response will be something like:

{
  "success": true,
  "invocations": {
    "object": "list",
    "limit": 40,
    "skip": 0,
    "totalCount": 0,
    "data": []
  }
}

where, in this case, there have been no invocations on that webhook.

Delete a Webhook

This function will delete a Webhook that's currently being used for callbacks.

const doc = await client.webhook.delete(id)

where id is the Letter ID, like webhook_rqjK6m3T71butzwSd7zU4N, in the above example, and the response will be something like:

{
  "success": true,
  "webhook": {
    "id": "webhook_rqjK6m3T71butzwSd7zU4N",
    "object": "webhook",
    "deleted": true
  }
}

Development

For those interested in working on the library, there are a few things that will make that job a little simpler. The organization of the code is all in src/, with one module per section of the Client: contact, letter, template, etc. This makes location of the function very easy.

Additionally, the main communication with the PostGrid service is in the src/index.ts module in the fire() function. In the constructor for the Client, each of the sections are created, and then they link back to the main class for their communication work.

Setup

In order to work with the code, the development dependencies include dotenv so that each user can create a .env file with a single value for working with PostGrid:

  • POSTGRID_API_KEY - this is the API Key referred to, above, and can be created on the PostGrid Dashboard page

Testing

There are several test scripts that create, test, and tear-down, state on the PostGrid service exercising different parts of the API. Each is self-contained, and can be run with:

$ npm run ts tests/contacts.ts
creating a single Contact...
Success!
fetching a single Contact...
Success!
listing the first page of 40 Contacts...
Success!
deleting a single Contact...
Success!

Each of the tests will run a series of calls through the Client, and check the results to see that the operation succeeded. As shown, if the steps all report back with Success! then things are working.

If there is an issue with one of the calls, then an Error! will be printed out, and the data returned from the client will be dumped to the console.