Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Integration With Zapier

DZone's Guide to

Integration With Zapier

While most devs use integration techniques a lot, it's not always the most thrilling thing in the world. Read on to learn how to make that process a little easier.

· Integration Zone ·
Free Resource

The new Gartner Critical Capabilities report explains how APIs and microservices enable digital leaders to deliver better B2B, open banking and mobile projects.

Integration is boring. And also inevitable. But I won't be writing about enterprise integration patterns. Instead, I'll explain how to create an app for integration with Zapier.

What is Zapier? It is a service that allows you tо connect two (or more) otherwise unconnected services via their APIs (or protocols). You can do stuff like: "Create a Trello task from an Evernote note"; "publish new RSS items to Facebook"; "append new emails to a spreadsheet"; "post approaching calendar meeting to Slack"; "Save big email attachments to Dropbox"; "tweet all instagrams above a certain likes threshold"; and so on. In fact, it looks to cover mostly the same use cases as another famous service that I really like - IFTTT (if this then that), with my favorite use-case being, "Get a notification when the international space station passes over your house." And all of those interactions can be configured via a UI.

Now that's good for end users but what does it have to do with software development and integration? Zapier (unlike IFTTT, unfortunately), allows custom 3rd party services to be included. So if you have a service of your own, you can create an "app" and allow users to integrate your service with all the other 3rd party services. IFTTT offers a way to invoke web endpoints (including RESTful services), but it doesn't allow setting headers, so that makes it quite limited for actual APIs.

In this post, I'll briefly explain how to write a custom Zapier app and then will discuss where services like Zapier stand from an architecture perspective.

The thing that I needed it for - to be able to integrate LogSentinel with any of the third parties available through Zapier, i.e. to store audit logs for events that happen in all those 3rd party systems. So how do I do that? There's a tutorial that makes it look simple. And it is, with a few catches.

First, there are two tutorials - one on GitHub and one on Zapier's website. And they differ slightly, which becomes tricky in some cases.

I initially followed the GitHub tutorial and had my build fail. It claimed the Zapier platform dependency is missing. After I compared it with the example apps, I found out there's a caret in front of the Zapier platform dependency. Removing it just yielded another error - that my node version should be exactly 6.10.2. Why?

The Zapier CLI requires you have exactly version 6.10.2 installed. You'll see errors and will be unable to proceed otherwise.

It appears that they are using AWS Lambda which is stuck on Node 6.10.2 (actually - it's 6.10.3 when you check). The current major release is 8, so minus points for choosing ... JavaScript for a command-line tool and for building sandboxed apps. Maybe other decisions had their downsides as well, I won't be speculating. Maybe it's just my dislike for dynamic languages.

So, after you make sure you have the correct old version on node, you call zapier init and make sure there are no carets, npm install and then zapier test. So far so good, you have a dummy app. Now how do you make a RESTful call to your service?

Zapier splits the programmable entities into two - "triggers" and "creates." A trigger is an event that triggers the whole app, and a "create" is what happens as a result. In my case, my app doesn't publish any triggers, it only accepts input, so I won't be mentioning triggers (though they seem easy). You configure all of the elements in index.js (e.g. this one):

const log = require('./creates/log');
....
creates: {
    [log.key]: log,
}

The log.js file itself is the interesting bit - there, you specify all the parameters that should be passed to your API call, as well as make the API call itself:

const log = (z, bundle) => {
  const responsePromise = z.request({
    method: 'POST',
    url: `https://api.logsentinel.com/api/log/${bundle.inputData.actorId}/${bundle.inputData.action}`,
    body: bundle.inputData.details,
headers: {
'Accept': 'application/json'
}
  });
  return responsePromise
    .then(response => JSON.parse(response.content));
};

module.exports = {
  key: 'log-entry',
  noun: 'Log entry',

  display: {
    label: 'Log',
    description: 'Log an audit trail entry'
  },

  operation: {
    inputFields: [
      {key: 'actorId', label:'ActorID', required: true},
      {key: 'action', label:'Action', required: true},
      {key: 'details', label:'Details', required: false}
    ],
    perform: log
  }
};

You can pass the input parameters to your API call, and it's as simple as that. The user can then specify which parameters from the source ("trigger") should be mapped to each of your parameters. In an example zap, I used an email trigger and passed the sender as actorId, the subject as "action," and the body of the email as details.

There's one more thing - authentication. Authentication can be done in many ways. Some services offer OAuth, others use HTTP Basic or other custom forms of authentication. There is a section in the documentation about all the options. In my case, it was (almost) an HTTP Basic auth. My initial thought was to just supply the credentials as parameters (which you just hardcode rather than map to trigger parameters). That may work, but it's not the canonical way. You should configure "authentication," as it triggers a friendly UI for the user.

You include authentication.js (which has the fields your authentication requires) and then pre-process requests by adding a header (in index.js):

const authentication = require('./authentication');

const includeAuthHeaders = (request, z, bundle) => {
  if (bundle.authData.organizationId) {
request.headers = request.headers || {};
request.headers['Application-Id'] = bundle.authData.applicationId
const basicHash = Buffer(`${bundle.authData.organizationId}:${bundle.authData.apiSecret}`).toString('base64');
request.headers['Authorization'] = `Basic ${basicHash}`;
  }
  return request;
};

const App = {
  // This is just shorthand to reference the installed dependencies you have. Zapier will
  // need to know these before we can upload
  version: require('./package.json').version,
  platformVersion: require('zapier-platform-core').version,
  authentication: authentication,

  // beforeRequest & afterResponse are optional hooks into the provided HTTP client
  beforeRequest: [
includeAuthHeaders
  ]
...
}

And then you zapier push your app and you can test it. It doesn't automatically go live, as you have to invite people to try it and use it first, but, in many cases, that's sufficient (i.e. using Zapier when doing integration with a particular client).

Can Zapier can be used for any integration problem? Unlikely - it's pretty limited and simple, but that's also a strength. You can, in half a day, make your service integrate with thousands of others for the most typical use-cases. And note that although it's meant for integrating public services rather than for enterprise integration (where you make multiple internal systems talk to each other), as an increasing number of systems rely on 3rd party services, it could find a home in an enterprise system, replacing some functions of an ESB.

Effectively, such services (Zapier, IFTTT) are "Simple ESB-as-a-service." You go to a UI, fill in a bunch of fields, and you get systems talking to each other without touching the systems themselves. I'm not a big fan of ESBs, mostly because they become harder to support with time. But minimalist, external ones might be applicable in certain situations. And while such services are primarily aimed at end users, they could be a useful bit in an enterprise architecture that relies on 3rd party services.

Whether it could process the required load, whether an organization is willing to let its data flow through a 3rd party provider (which may store the intermediate parameters), is a question that should be answered on a case by case basis. I wouldn't recommend it as a general solution, but it's certainly an option to consider.

The new Gartner Critical Capabilities for Full Lifecycle API Management report shows how CA Technologies helps digital leaders with their B2B, open banking, and mobile initiatives. Get your copy from CA Technologies.

Topics:
integration ,application integration ,zapier

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}