GraV-IT
← All work

2019 · Lead developer · Oct 2019 – Apr 2026

SignerX Zapier App

For SignerX

A supporting connector for the SignerX API — a published Zapier integration that lets any SignerX user wire document-signing events into the rest of their stack without writing code. Built across both halves of the system — the Zapier app (Node + Zapier Platform CLI, OAuth2 with PKCE, hidden lookups powering dynamic dropdowns) and the SignerX API (extended Passport OAuth client for branded consent, response-shaping middleware to keep the Zapier app declarative).

Stack
Zapier Platform CLI Node.js JavaScript OAuth2 (PKCE) Laravel Passport Laravel

The brief

The SignerX Zapier App is a connector — a supporting tool for the SignerX API that lets a SignerX user trigger automations off document-signing events without writing code. A Slack notification when a contract is signed, a HubSpot deal advanced when a package is sent, a Google Sheet of recipients kept up to date — all configured by the customer in Zapier, not by us. The published listing on Zapier’s marketplace means it shows up alongside thousands of other integrations, available to any SignerX customer who wants it.

I designed and built both halves. The Zapier app itself (Node, Zapier Platform CLI) and the SignerX API surface that makes the integration possible (Laravel Passport for OAuth2, response-shaping middleware, extended OAuth client metadata so SignerX shows up branded on the authorization screen, not generic).

What I built

OAuth2 with PKCE. SignerX users authorize Zapier through a standard OAuth2 flow with PKCE enabled, the security model Zapier requires for public clients. Auto token refresh on the Zapier side, profile-checking endpoint on the API side, connection labels that surface the user’s email so anyone managing multiple SignerX accounts in Zapier can tell them apart at a glance.

Branded OAuth consent, via extended Passport metadata. The authorization screen a SignerX user sees when they connect Zapier shows the SignerX logo, display name, terms-of-service URL, and privacy-policy URL — not the default Passport scaffolding. That meant extending the Passport Client model on the Laravel side (icon_url, display_name, tos_url, pp_url) and feeding that metadata into the consent flow. Small detail, big trust gain at the moment a user is granting access.

Three triggers, two actions, one published of each. The user-facing trigger is Package Sent — fires when a SignerX package is dispatched for signature, with 25+ payload fields exposed for use in downstream Zaps. The user-facing action is Send Template for Signatures. The other triggers (Get Packages, Get Templates) and the second action (Upload Document) are marked hidden: true: they don’t show up in Zapier’s trigger picker, but they power the dynamic dropdowns inside the visible actions (when a user is configuring “Send Template for Signatures,” the template dropdown is populated at runtime by the hidden get_templates trigger). It’s the right pattern for surfacing internal API endpoints as helpful UX without cluttering the choices a user sees.

Zapier-aware response middleware on the API. Zapier expects specific response shapes — single-item operations return objects, list operations return arrays, empty arrays on certain endpoints need to be coerced to objects to avoid bad downstream parsing. A ZapierReturnArrayMiddleware on the SignerX API detects requests coming from the Zapier OAuth client (by name) and reshapes the response on the way out. The Zapier app code stays clean and declarative; the polymorphism lives in the middleware where it belongs.

What’s notable about it

The integration is the work; the architecture is what made it maintainable. Two codebases evolved together — the Node app on the Zapier side and the Laravel API on the SignerX side — and the integration glue lives in the right places. Response shaping is on the API; OAuth metadata extends Passport; the Zapier app stays a thin, declarative shell over endpoints that already do the work. That’s what lets a published integration ship through years of product changes without rotting.