Hello World of Contracts

Covers the basics of Ironclad's API with a simple example of storing all signed contracts to a custom datastore.

Ironclad Workflows help manage contracts, from request, to negotiation, to execution. While Ironclad's out-of-the-box integrations with cloud storage providers keep contract documents in sync automatically, you may want to use the API to persist signed agreements to an internal system, or customize where it is stored.

In this guide, we will go over:

  • Setting up API tokens
  • Configuring a webhook in the UI
  • Querying Ironclad's Workflow APIs to retrieve signed contract PDFs

You will need:

  • An Ironclad user account, with access to a simple workflow and API (Power User) access.
  • A development environment and a system for receiving webhooks, like ngrok.

Setting up API Tokens

Log into Ironclad, and navigate to the API configuration page, which will be in the dropdown menu in the top-right. From this page, you can create a new API token. Copy and save the token, since you will not be able to retrieve this token later.

Configuring a Webhook

Start by setting up a simple application endpoint. The example below uses Node.js with Express.

const express = require('express');

const app = express();

app.use(express.json());

app.post('/webhook', (request, response) => {
  let payload;

  try {
    payload = request.body.payload;
  } catch (err) {
    response.sendStatus(400);
  }

  // Get the type of event that triggered this webhook.
  const event = payload.event;
  // Get the ID of the workflow that updated.
  const workflowID = payload.workflowID;

  switch (event) {
    case 'workflow_launched':
      console.log(`launched workflow: ${workflowID}`);
      break;
    case 'workflow_completed':
      console.log(`completed workflow: ${workflowID}`);
      break;
    default:
      console.log(`received event type: ${event}`);
  }

  // Acknowledge receipt of the webhook.
  response.sendStatus(200);
});

app.listen(3000, () => console.log('Listening for webhook on port 3000'));

Once you have your simple endpoint running locally, set up a tunnel with a tool like ngrok, and direct it to port 3000. (With ngrok, you would run ngrok http 3000.)

From the Ironclad API page, click "Create Webhook," and copy and paste the tunnel URL into the "Target HTTP URL" field (adding /webhook to it, so that it looks something like http://abcde.ngrok.io/webhook).

Adding a webhook in the UI.

Launch a workflow, and you should see a simple webhook event.

Note that webhooks can be configured directly via the API, and supports verification via signatures included in the header.

Querying for Signed PDF

Now that Ironclad is pushing webhook events to our application, let's query for workflow information from the workflow API. With the code below, we request attribute information from the workflow, and if the signed document is present, we download it.

require('dotenv').config();
const fs = require('fs');
const express = require('express');
const axios = require('axios').default;

const app = express();

// Be sure to store your API securely!
const apiKey = process.env.API_KEY;

// Your host URL may vary based on the implementation.
const hostUrl = (process.env.HOST_URL ? process.env.HOST_URL : 'ironcladapp');
const apiUrl = `https://${hostUrl}.com/public/api/v1`;

app.use(express.json());

app.post('/webhook', async (request, response) => {
  let payload;

  try {
    payload = request.body.payload;
  } catch (err) {
    return response.sendStatus(400);
  }

  // Retrieve workflow information through GET endpoint
  const workflowID = payload.workflowID;
  const workflowResponse = await axios.get(
    `${apiUrl}/workflows/${workflowID}`, {
      headers: {
        Authorization: `Bearer ${apiKey}`,
      },
    },
  );

  const {data} = workflowResponse;

  // If the signed agreement is present, retrieve it and store it.
  if (data.attributes.signed) {
    const signedDocResponse = await axios.get(
      `https://${hostUrl}.com${data.attributes.signed.download}`,
      {
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
        responseType: 'stream',
      },
    );

    signedDocResponse.data.pipe(
      fs.createWriteStream(`contract-${workflowID}.pdf`),
    );
    console.log(`copied signed document for workflow: ${data.title}`);
  } else {
    console.log(`update from in-progress workflow: ${data.title}`);
  }

  // Acknowledge receipt of the webhook.
  response.sendStatus(200);
});

app.listen(3000, () => console.log('Listening for webhook on port 3000'));