Recipes

n8n

Add a contact from a form, and start a workflow when a contact is created. Both use n8n’s HTTP Request node with header authentication.

Set up the key

  1. In ContactZapp, create an API key with both scopes. See Getting started.
  2. In n8n, open Credentials, then Create credential, and choose Header Auth. Fill it in as below, and name it ContactZapp API key.
    FieldValue
    NameAuthorization
    ValueBearer cz_live_… (your key)

Add a contact from a form

The workflow takes the fields of a form submission and sends them to POST /api/v1/contacts. The first node stands in for your form: replace it with n8n’s Form Trigger, a Webhook, or whatever starts your workflow.

The HTTP Request node is set like this:

SettingValue
MethodPOST
URLhttps://app.contactz.app/api/v1/contacts
AuthenticationGeneric Credential Type, then Header Auth: ContactZapp API key
Send HeadersOn. Idempotency-Key is a value that is yours for this one submission, such as the submission id.
Send BodyOn, JSON, using the fields of a contact. See Creating and changing contacts.
Settings, Retry On FailOn, 3 tries. The Idempotency-Key makes a retry safe.
The workflow, to paste into n8n

Copy it, then paste it onto the n8n canvas. Choose your own credential on the HTTP Request node.

ContactZapp: add a contact
{
  "name": "ContactZapp: add a contact",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "submissionId",
              "value": "form-1001",
              "type": "string"
            },
            {
              "id": "a2",
              "name": "firstName",
              "value": "Grace",
              "type": "string"
            },
            {
              "id": "a3",
              "name": "lastName",
              "value": "Hopper",
              "type": "string"
            },
            {
              "id": "a4",
              "name": "email",
              "value": "[email protected]",
              "type": "string"
            },
            {
              "id": "a5",
              "name": "phone",
              "value": "+1 202 555 0147",
              "type": "string"
            },
            {
              "id": "a6",
              "name": "company",
              "value": "Navy",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Form data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://app.contactz.app/api/v1/contacts",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Idempotency-Key",
              "value": "={{ $json.submissionId }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { firstName: $json.firstName, lastName: $json.lastName, organization: $json.company, emails: [{ label: 'work', value: $json.email }], phones: [{ label: 'mobile', value: $json.phone }] } }}",
        "options": {}
      },
      "name": "Add contact",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "REPLACE",
          "name": "ContactZapp API key"
        }
      }
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Form data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Form data": {
      "main": [
        [
          {
            "node": "Add contact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

The answer has an outcome: created, merged or needs_review. Add an IF node after the HTTP Request node if your workflow should act on it.

Start a workflow when a contact is created

n8n has no ContactZapp trigger, so the workflow polls GET /api/v1/triggers/contact.created every 5 minutes. Each event has a stable id. The Remove Duplicates node remembers the ids it has seen, so a later run passes on only the new events.

The workflow, to paste into n8n
ContactZapp: a contact was created
{
  "name": "ContactZapp: a contact was created",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 5
            }
          ]
        }
      },
      "name": "Every 5 minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "https://app.contactz.app/api/v1/triggers/contact.created",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "50"
            }
          ]
        },
        "options": {}
      },
      "name": "Get new contacts",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        220,
        0
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "REPLACE",
          "name": "ContactZapp API key"
        }
      }
    },
    {
      "parameters": {
        "fieldToSplitOut": "items",
        "options": {}
      },
      "name": "One item per event",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "operation": "removeItemsSeenInPreviousExecutions",
        "dedupeValue": "={{ $json.id }}",
        "options": {}
      },
      "name": "Only events not seen before",
      "type": "n8n-nodes-base.removeDuplicates",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b1",
              "name": "name",
              "value": "={{ $json.contact.displayName }}",
              "type": "string"
            },
            {
              "id": "b2",
              "name": "email",
              "value": "={{ $json.contact.emails[0]?.value ?? '' }}",
              "type": "string"
            },
            {
              "id": "b3",
              "name": "frozen",
              "value": "={{ $json.contact.frozen }}",
              "type": "boolean"
            }
          ]
        },
        "options": {}
      },
      "name": "Your next step",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        880,
        0
      ]
    }
  ],
  "connections": {
    "Every 5 minutes": {
      "main": [
        [
          {
            "node": "Get new contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get new contacts": {
      "main": [
        [
          {
            "node": "One item per event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "One item per event": {
      "main": [
        [
          {
            "node": "Only events not seen before",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only events not seen before": {
      "main": [
        [
          {
            "node": "Your next step",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

Tested with n8n 1.100.1.