anvilco / node-anvil

Node API Client for Anvil
https://www.useanvil.com/developers/
17 stars 6 forks source link
e-sign e-signature javascript nodejs pdf pdf-fill pdf-generation

Horizontal Lockupblack Horizontal Lockup copywhite

Anvil API Client for Node

This library will allow you to interact with the Anvil API in JavaScript / NodeJS.

Anvil provides easy APIs for all things paperwork.

  1. PDF filling API - fill out a PDF template with a web request and structured JSON data.
  2. PDF generation API - send markdown or HTML and Anvil will render it to a PDF.
  3. Etch e-sign with API - customizable, embeddable, e-signature platform with an API to control the signing process end-to-end.
  4. Anvil Workflows (w/ API) - Webforms + PDF + e-sign with a powerful no-code builder. Easily collect structured data, generate PDFs, and request signatures.

Learn more on our Anvil developer page. See the API guide and the GraphQL reference for full documentation.

Usage

This library and the Anvil APIs are intended to be used on a server or server-like environment. It will fail in a browser environment.

yarn add @anvilco/anvil
npm install @anvilco/anvil

A basic example converting your JSON to a filled PDF, then saving the PDF to a file:

import fs from 'fs'
import Anvil from '@anvilco/anvil'

// The ID of the PDF template to fill
const pdfTemplateID = 'kA6Da9CuGqUtc6QiBDRR'
// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'

// JSON data to fill the PDF
const exampleData = {
  "title": "My PDF Title",
  "fontSize": 10,
  "textColor": "#CC0000",
  "data": {
    "someFieldId": "Hello World!"
  }
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, exampleData)

// By default, if the PDF has been published then the published version is what will
// be filled. If the PDF has not been published, then the most recent version will
// be filled. 
// 
// However, a version number can also be passed in that will be used retrieve and
// fill a specific version of the PDF.
// You can also use the constant `Anvil.VERSION_LATEST` (or `-1`) to fill the most 
// recent version of your PDF, whether that version has been published or not.
// Use this if you'd like to fill out a draft version of your template/PDF.
const options = { versionNumber: Anvil.VERSION_LATEST }
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, exampleData, options)

console.log(statusCode) // => 200

// Data will be the filled PDF raw bytes
fs.writeFileSync('output.pdf', data, { encoding: null })

API

Instance Methods

new Anvil(options)

Creates an Anvil client instance.

const anvilClient = new Anvil({ apiKey: 'abc123' })


fillPDF(pdfTemplateID, payload[, options])

Fills a PDF template with your JSON data.

First, you will need to have uploaded a PDF to Anvil. You can find the PDF template's id on the API Info tab of your PDF template's page:

pdf-template-id

An example:

const fs = require('fs')

// PDF template you uploaded to Anvil
const pdfTemplateID = 'kA6Da9CuGqUtc6QiBDRR'

// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'

// JSON data to fill the PDF
const payload = {
  "title": "My PDF Title",
  "fontSize": 10,
  "textColor": "#CC0000",
  "data": {
    "someFieldId": "Hello World!"
  }
}
// The 'options' parameter is optional
const options = {
  "dataType": "buffer"
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, payload, options)

// Be sure to write the file as raw bytes
fs.writeFileSync('filled.pdf', data, { encoding: null })
generatePDF(payload[, options])

Dynamically generate a new PDF from your HTML and CSS or markdown.

Useful for agreements, invoices, disclosures, or any other text-heavy documents. This does not require you do anything in the Anvil UI other than setup your API key, just send it data, get a PDF. See the generate PDF docs for full details.

Check out our HTML invoice template for a complete HTML to PDF example.

An example:

const fs = require('fs')

// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'

// An example using an HTML to PDF payload
const payload = {
  title: 'Example',
  type: 'html',
  data: {
    html: `
      <h1 class='header-one'>What is Lorem Ipsum?</h1>
      <p>
        Lorem Ipsum is simply dummy text...
      </p>
      <h3 class='header-two'>Where does it come from?</h3>
      <p>
        Contrary to popular belief, Lorem Ipsum is not simply <i>random text</i>
      </p>
    `,
    css: `
      body { font-size: 14px; color: #171717; }
      .header-one { text-decoration: underline; }
      .header-two { font-style: underline; }
    `,
  },
}

// An example using a Markdown payload
const payload = {
  title: 'Example Invoice',
  data: [{
    label: 'Name',
    content: 'Sally Jones',
  }, {
    content: 'Lorem **ipsum** dolor sit _amet_',
  }, {
    table: {
      firstRowHeaders: true,
      rows: [
        ['Description', 'Quantity', 'Price'],
        ['4x Large Widgets', '4', '$40.00'],
        ['10x Medium Sized Widgets in dark blue', '10', '$100.00'],
        ['10x Small Widgets in white', '6', '$60.00'],
      ],
    },
  }],
}
// The 'options' parameter is optional
const options = {
  "dataType": "buffer"
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.generatePDF(payload, options)

// Be sure to write the file as raw bytes
fs.writeFileSync('generated.pdf', data, { encoding: null })
createEtchPacket(options)

Creates an Etch Packet and optionally sends it to the first signer.

getEtchPacket(options)

Gets the details of an Etch Packet.

generateEtchSignUrl(options)

Generates an Etch sign URL for an Etch Packet signer. The Etch Packet and its signers must have already been created.

downloadDocuments(documentGroupEid[, options])

Returns a Buffer, ArrayBuffer, or Stream of the document group specified by the documentGroupEid in Zip file format.

requestGraphQL(queryInfo[, options])

A fallback function for queries and mutations without a specialized function in this client.

See the GraphQL reference for a listing on all possible queries

const result = await client.requestGraphQL({
  query: `
    query WeldDataQuery ($eid: String!) {
      weldData (eid: $eid) {
        eid
        isComplete
        isTest
      }
    }
  `,
  variables: { eid: 'nxflNZqxDUbltLUbYWK' },
})
const statusCode = result.statusCode
const httpErrors = result.errors

// These will only be available if the statusCode === 200
const graphqlErrors = result.data.errors
const resultObject = result.data.data.weldData
requestREST(url, fetchOptions[, clientOptions])

A fallback function for REST endpoints without a specialized function in this client.

See the GraphQL reference for a listing on all possible queries

const result = await this.requestREST(
  `/api/v1/fill/${pdfTemplateID}.pdf`,
  {
    method: 'POST',
    body: JSON.stringify(payload),
    headers: {
      'Content-Type': 'application/json',
    },
  },
  {
    dataType: 'stream',
  },
)

Class Methods

prepareGraphQLFile(pathOrStreamLikeThing[, options])

A nice helper to prepare a File upload for use with our GraphQL API. By default, this will upload your files as multipart uploads over the jaydenseric / GraphQL multipart request spec. We use node-fetch under the hood, and you can see this example to get a bit of an understanding of what's happening behind the scenes. NOTE: Please see below about certain scenarios where you may need to manually provide a filename.

Types

Options

Options for the Anvil Client. Defaults are shown after each option key.

{
  apiKey: <your_api_key>, // Required. Your API key from your Anvil  organization settings
}

Rate Limits

Our API has request rate limits in place. The initial request made by this client will parse the limits for your account from the response headers, and then handle the throttling of subsequent requests for you automatically. In the event that this client still receives a 429 Too Many Requests error response, it will wait the specified duration then retry the request. The client attempts to avoid 429 errors by throttling requests after the number of requests within the specified time period has been reached.

See the Anvil API docs for more information on the specifics of the rate limits.

API Documentation

Our general API Documentation can be found here. It's the best resource for up-to-date information about our API and its capabilities.

See the PDF filling API docs for more information about the fillPDF method.

Examples

Check out the example folder for running usage examples!

Development

First install the dependencies

yarn install

Running tests

yarn test
yarn test:watch

Building with babel will output in the /lib directory.

yarn test

# Watches the `src` and `test` directories
yarn test:watch