This guide will teach you how to automatically update a Web3 based CRM (in this case, once you have a new signup to your dapp.

Holder is a CRM and marketing automation platform built uniquely to handle web3 and wallet data. With Holder + Dynamic, you can:

  • Have a single view of your customers, unifying Dynamic user information with your CRM and marketing data.
  • Enable powerful on-chain automations and marketing campaigns (like XMTP messaging) based on Dynamic webhook events.


This guide builds on the serverless guide, so you should have already completed that guide and have a working serverless function. It also assumes you already have a Holder account.

Step 1: Get your Authentication token

For, you’ll need to follow a couple of steps in order to get the token you’ll need to authenticate with the API. The fastest way is to follow this guide: Come back here once you have your token!

You’ll be passing this in the header of API requests like so:

  "headers": {
    "Authorization": "Bearer Your_Token_Here"

Step 2: Define your API request

The choice is yours as to which library you use, we will use Fetch here.

First we need to know our base URL, which is We will be using the POST method to create a new user, and we will be hitting the /contacts endpoint. The full reference for that endpoint is here.

We need to pass a primaryIdentifier which in our case will be email, and a value, which is the email itself. So putting it together it will look something like this:

// holder.js

const token = XXXX;

const createUserInCrm = async (userEmail) => {
  const options = {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    body: `{"primaryIdentifier":"email", "value": ${userEmail}}`,

  try {
    return await fetch("", options);
  } catch (error) {

module.exports = createUserInCrm;

Step 3: Plug in your serverless function

Going back to our Serverless guide at Step 3, all we have to do now is add in our Holder function call:

// index.js

const createUserInCrm = require("./holder");

module.exports.handler = async (event) => {
  const email =;

  await createUserInCrm(email);

  return {
    statusCode: 200,
    body: JSON.stringify(
        message: "Go Serverless v3.0! Your function executed successfully!",
        input: event,

You can then test and redeploy your function as in Step 4 of the serverless guide, and you’re done!

You should see a new contact in the Holder app like so:

The next step you might want to take is to update the contact if the user adds more details to their Dynamic profile i.e. wallet addresses etc. We will cover this in a further guide, so stay tuned!