GTM Playbooks

Rebook Demo No-Shows with a Short Personalized Sequence

The problem

Booked demos that end as no-shows usually get one "sorry we missed you" email or nothing at all, so meetings the team already worked to create quietly drop out of the pipeline.

Implementation steps

  1. 1

    Decide where no-shows are recorded: Calendly's mark-as-no-show option (which can fire an invitee no-show webhook), the meeting outcome on HubSpot meetings (it includes a No show value), or an outcome field on Salesforce events for meetings booked through Chili Piper

  2. 2

    Send each no-show to a Clay webhook with the invitee email, name, company, meeting type, scheduled time, booking form answers, and the meeting owner, from a CRM workflow that fires when the outcome changes to no-show or from a Zapier or Make relay

  3. 3

    Look up the contact and any open deal in the CRM, and stop if a new meeting is already booked or the deal is closed

  4. 4

    Use an AI step to write a two-sentence rebook note from the rep that refers to what they asked about when booking, with no guilt or pressure, and fall back to a fixed template when the booking answers are empty

  5. 5

    Flag the contact so a CRM workflow enrolls them in a short rebook sequence from the meeting owner, for example three touches over a week with the rep's booking link, using HubSpot sequences or Salesforce cadences, and stops as soon as a new meeting is booked

  6. 6

    Create a same-day task for the rep to call or send a personal note, post the drafted note to the rep in Slack, and record the no-show date on the contact so repeat no-shows can be routed differently

Template outline

The structure to recreate in your own workspace. Field names and thresholds are starting points.

Clay Workflow (webhook trigger, one run per no-show):
1. Source: Calendly no-show webhook (via relay), HubSpot meeting outcome = No show, or Salesforce event outcome field
2. Webhook payload: email, first_name, company, meeting_type, scheduled_at, form_answers, rep_email, rep_first_name
3. CRM lookup: contact, open deal stage, next meeting or activity date
4. Stop IF a new meeting is booked OR the deal is closed
5. AI prompt: "Write two sentences from {{rep_first_name}} to {{first_name}}, who missed {{meeting_type}}. Refer to: {{form_answers}}. Offer another time. No guilt, no urgency tricks."
6. CRM update: rebook note, rebook needed = true, last no-show date
7. CRM workflow on rebook needed = true:
   - Enroll in rebook sequence (3 touches over a week, owner as sender, booking link in each)
   - Task: "Call or write to {{first_name}} today"
   - Unenroll when a meeting is booked
8. Slack to rep: invitee, company, booking answers, drafted note
Output: every no-show gets a personal rebook attempt the same day, and reps see which booked demos still need a new time

Build it in Clay

Clay CLI v1.3.1

Copy these commands into your own Clay CLI. They run in your Clay workspace under your login. Nothing runs on our side, and this site never sees your Clay data or login.

This builds the no-show play as a Clay workflow with a webhook trigger. Each no-show becomes one run: look up the contact in the CRM, write a short rebook note from their booking answers, write the note and a rebook flag back to the CRM, and tell the rep in Slack. A CRM workflow that watches the flag enrolls the contact in your rebook sequence and creates the rep task, since sequences and tasks live in the CRM. The Clay CLI cannot create tables, so this build uses a workflow.

Not tested by GTM Playbooks

This build was written from the Clay CLI v1.3.1 help output, not from a run. Anything marked “Verify in your workspace”, and every line tagged VERIFY in the script, uses a shape that help does not document. Workflow runs can spend your Clay credits.

Part 1: Before you start

  1. 1.Install the Clay CLI

    Use version 1.3.1 or later, installed from Clay's own instructions. This page does not include an install command because the CLI reference it was written from does not list one. You also need jq, which the script uses to read the JSON the CLI prints.

  2. 2.Log in to your workspace

    Browser login is the default. Use the device flow on a headless machine. A static key in the CLAY_API_KEY environment variable also works. Workflow commands need the terracotta:cli scope, so an auth error that names it means your login cannot manage workflows.

    Log in with a browser

    clay login

    Log in on a headless machine

    clay login --device

    Confirm who you are logged in as

    clay whoami
  3. 3.Pick the workspace to build in

    The workflow is created in your active workspace. Switch first if you belong to more than one.

    List workspaces

    clay workspaces list

    Show the active workspace

    clay workspaces current

    Switch workspace

    clay workspaces switch <workspaceId>
  4. 4.Find your action keys

    Action package ids and keys are specific to your workspace. Save the catalog, search it for your CRM lookup action, an AI text action, your CRM update action, and Slack, then paste their ids into the top of the script. Skip "clay workflows actions test": it spends credits.

    Save the action catalog

    clay workflows actions list > catalog.json

    Search the catalog

    grep -Eio '"[^"]*(hubspot|salesforce|lookup|find|use ai|generate|slack)[^"]*"' catalog.json | sort -u

    See an action's inputs and outputs

    clay workflows actions schema <packageId> <actionKey>
  5. 5.Decide what sends no-shows to the webhook

    Use a HubSpot or Salesforce workflow that fires when a meeting outcome changes to no-show, or Calendly's invitee no-show webhook through a Zapier or Make relay that flattens it to the fields in the sample payload. Chili Piper bookings land in your CRM, so record their no-shows in the CRM outcome field and use the CRM route.

  6. 6.Set up the CRM side

    Create contact properties for rebook note, rebook needed, and last no-show date. Build a CRM workflow that, when rebook needed is true, enrolls the contact in a short rebook sequence from the meeting owner, creates a same-day task for the rep, and clears the flag. Make the sequence stop when a new meeting is booked.

Part 2: Workflow spec

What the script builds: Meeting no-show rebook.

Trigger

webhook

A CRM workflow or a relay POSTs one JSON object per no-show to the trigger's webhook URL. The fields arrive as run inputs as-is.

Verify in your workspace: Sending a webhook from a HubSpot workflow or a Salesforce flow depends on your CRM edition. A Zapier or Make relay works when the CRM cannot send one directly.

Inputs (webhook payload fields)

email
Invitee email
jane@example.com
first_name
Invitee first name
Jane
company
Company from the booking
Example Co
meeting_type
Meeting name or type
Product demo
scheduled_at
When the meeting was scheduled
2026-10-15 14:00 UTC
form_answers
Booking form answers as one string
Looking to automate lead routing for a 6-person SDR team
rep_email
Meeting owner email
rep@yourdomain.com
rep_first_name
Meeting owner first name
Sam
  1. 1

    Look up the contact and deal

    action

    Finds the contact and any open deal so the run can stop when a new meeting is already booked or the deal is closed.

    Reads
    email
    Writes
    contact_iddeal_stagenext_activity_date

    Verify in your workspace: The stop rule needs a run condition on later steps, which the CLI help does not document. Set it in the Clay UI using your CRM fields for deal stage and next activity or meeting date.

  2. 2

    Write the rebook note

    action

    An AI text action writes two sentences from the rep that refer to what the invitee asked about when booking.

    Reads
    first_namemeeting_typescheduled_atform_answersrep_first_name
    Writes
    rebook_note

    Prompt

    Write a two-sentence note from {{rep_first_name}} to {{first_name}}, who missed a {{meeting_type}} scheduled for {{scheduled_at}}. Refer to what they asked about when booking: {{form_answers}} Offer to find another time. Friendly and brief, no guilt, no urgency tricks, no em dashes. If the booking answers are empty, return exactly: EMPTY

    Verify in your workspace: When the note comes back as EMPTY, your CRM sequence should fall back to its fixed first email. Handle that in the sequence or with a formula.

  3. 3

    Flag the contact for rebooking

    action

    Updates the contact with the rebook note, rebook needed = true, and the no-show date, which starts the CRM workflow.

    Reads
    contact_idrebook_notescheduled_at
    Writes
    CRM record
  4. 4

    Tell the rep in Slack

    action

    Sends the rep the invitee, company, booking answers, and the drafted note so they can call or write personally the same day.

    Reads
    rep_emailfirst_namecompanymeeting_typeform_answersrebook_note
    Writes
    Slack message

Part 3: Build script

Creates the workflow, the webhook trigger, and four steps, then pauses so you can map step inputs and the stop condition. It validates the graph, offers one test run, and asks before publishing.

Save it as build-no-show-rebook.sh, fill in the 8 action ids at the top, then run bash build-no-show-rebook.sh.

build-no-show-rebook.sh

#!/usr/bin/env bash# Builds the "Meeting no-show rebook" Clay workflow# in YOUR Clay workspace, using YOUR Clay CLI login.# Written against Clay CLI v1.3.1. Not run or tested by GTM Playbooks.# Lines tagged VERIFY use a shape the CLI help does not document.set -euo pipefail # Copy these from catalog.json (see "Find your action keys").LOOKUP_PACKAGE_ID="" # HubSpot or Salesforce: find or lookup recordLOOKUP_ACTION_KEY=""WRITER_PACKAGE_ID="" # Use AI or another AI text actionWRITER_ACTION_KEY=""CRM_PACKAGE_ID=""    # HubSpot or Salesforce: update recordCRM_ACTION_KEY=""SLACK_PACKAGE_ID=""  # Slack: send messageSLACK_ACTION_KEY="" # One input to test before real traffic. Use yourself or a teammate.TEST_ROW='{"email":"","first_name":"","company":"","meeting_type":"","scheduled_at":"","form_answers":"","rep_email":"","rep_first_name":""}' for v in LOOKUP_PACKAGE_ID LOOKUP_ACTION_KEY WRITER_PACKAGE_ID WRITER_ACTION_KEY CRM_PACKAGE_ID CRM_ACTION_KEY SLACK_PACKAGE_ID SLACK_ACTION_KEY; do  [[ -n "${!v}" ]] || { echo "Set $v at the top of this script." >&2; exit 1; }donecommand -v clay > /dev/null || { echo "Clay CLI not found on PATH." >&2; exit 1; }command -v jq > /dev/null || { echo "jq is required to read CLI output." >&2; exit 1; }clay whoami > /dev/null || { echo "Not logged in. Run: clay login" >&2; exit 1; } # VERIFY: only "workflows create" documents an "id" field in its output.read_id() {  local id  id=$(jq -r '.id // empty' "$1")  [[ -n "$id" ]] || { echo "No id found in $1. Open it and adjust read_id." >&2; exit 1; }  echo "$id"} mkdir -p clay-no-show-rebookcd clay-no-show-rebook echo "1/8 Create the workflow"clay workflows create --name "Meeting no-show rebook" > workflow.jsonWF_ID=$(read_id workflow.json)WF_URL=$(jq -r '.url // empty' workflow.json) echo "2/8 Add the webhook trigger"clay workflows triggers create "$WF_ID" --input '{"triggerType":"webhook","inputSchema":{"type":"object"}}' > trigger.jsonTRG_ID=$(read_id trigger.json) echo "3/8 Step 1: look up the contact and deal"# VERIFY: help shows nodeType and name only; actionPackageId and actionKey are a guess.STEP1=$(jq -nc --arg p "$LOOKUP_PACKAGE_ID" --arg k "$LOOKUP_ACTION_KEY" '{nodeType: "tool", name: "Look up the contact and deal", actionPackageId: $p, actionKey: $k}')clay workflows nodes create "$WF_ID" --input "$STEP1" > step1.jsonSTEP1_ID=$(read_id step1.json) echo "4/8 Step 2: write the rebook note"# VERIFY: action fields inside "step" are inferred from the documented utility example.STEP2=$(jq -nc --arg n "$STEP1_ID" --arg p "$WRITER_PACKAGE_ID" --arg k "$WRITER_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')clay workflows nodes insert "$WF_ID" --input "$STEP2" > step2.jsonSTEP2_ID=$(read_id step2.json) echo "5/8 Step 3: flag the contact for rebooking"# VERIFY: same inferred insert shape as step 2.STEP3=$(jq -nc --arg n "$STEP2_ID" --arg p "$CRM_PACKAGE_ID" --arg k "$CRM_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')clay workflows nodes insert "$WF_ID" --input "$STEP3" > step3.jsonSTEP3_ID=$(read_id step3.json) echo "6/8 Step 4: tell the rep in slack"# VERIFY: same inferred insert shape as step 2.STEP4=$(jq -nc --arg n "$STEP3_ID" --arg p "$SLACK_PACKAGE_ID" --arg k "$SLACK_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')clay workflows nodes insert "$WF_ID" --input "$STEP4" > step4.jsonclay workflows graph get "$WF_ID" --mode full > graph.json echo "7/8 Map step inputs"cat <<EOF Step inputs are specific to your workspace. Map them before validating:  Step 1 lookup: email from the payload  Step 2 note:   first_name, meeting_type, scheduled_at, form_answers,                 rep_first_name, and the note prompt  Step 3 CRM:    contact id from step 1, rebook note, rebook needed = true,                 last no-show date = scheduled_at  Step 4 Slack:  rep_email, name, company, meeting type, answers, note  Add a run condition on steps 2 to 4: skip when a new meeting is booked  or the deal is closed.Map them in the Clay UI${WF_URL:+ at $WF_URL}, or per node with:  clay workflows nodes get $WF_ID <nodeId>  clay workflows nodes update $WF_ID <nodeId> --input node.jsongraph.json in this folder shows the current nodes and edges. EOFread -r -p "Press Enter when inputs are mapped. " echo "8/8 Validate, test once, publish"clay workflows graph validate "$WF_ID"clay workflows diagram "$WF_ID" if jq -e 'all(.[]; . != "")' <<< "$TEST_ROW" > /dev/null; then  read -r -p "Run TEST_ROW once? It can spend Clay credits, update your CRM (which can start the rebook sequence), and post to Slack. [y/N] " answer  if [[ "$answer" == [yY] ]]; then    clay workflows runs test "$WF_ID" --inputs "$TEST_ROW" > test-run.json    echo "Saved test-run.json. Check each step with: clay workflows runs steps $WF_ID <runId>"  fielse  echo "TEST_ROW is empty, skipping the test run."fi read -r -p "Publish the workflow now? [y/N] " answerif [[ "$answer" == [yY] ]]; then  clay workflows publish "$WF_ID" --name v1fi echo "Workflow $WF_ID, webhook trigger $TRG_ID. All responses are saved in $(pwd)."

Part 4: Sample no-show payload

Save this as clay-no-show-rebook/sample-no-show.json and use your own email as the invitee, so the CRM workflow it starts only reaches you.

sample-no-show.json

{  "email": "jane@example.com",  "first_name": "Jane",  "company": "Example Co",  "meeting_type": "Product demo",  "scheduled_at": "2026-10-15 14:00 UTC",  "form_answers": "Looking to automate lead routing for a 6-person SDR team",  "rep_email": "rep@yourdomain.com",  "rep_first_name": "Sam"}

Part 5: Send it a no-show

After publishing, read the webhook URL and send the sample payload once. Each POST is one run.

Load the saved ids (run inside clay-no-show-rebook/)

WF_ID=$(jq -r '.id' workflow.json); TRG_ID=$(jq -r '.id' trigger.json)

Read the webhook URL (argument order inferred, see the verify notes)

WEBHOOK_URL=$(clay workflows triggers get "$WF_ID" "$TRG_ID" | jq -r '.webhookUrl')

Send the sample payload (needs a published workflow, one run per request)

curl -sS -X POST "$WEBHOOK_URL" -H 'Content-Type: application/json' --data @sample-no-show.json

List runs

clay workflows runs list "$WF_ID"

Inspect one run

clay workflows runs get "$WF_ID" <runId>

See each step's output for that run

clay workflows runs steps "$WF_ID" <runId>

Verify in your workspace

The Clay CLI help does not document these details. Check each one before you rely on the build.

  • The webhook trigger shape comes from the CLI help, but the help does not say how "triggers get" orders its arguments. If the run commands fail, copy the webhook URL from the Clay UI instead.
  • The help documents "nodes create" with nodeType and name only. If it rejects actionPackageId and actionKey, create the node with a name only and pick the action in the Clay UI.
  • The reference says action steps take actionPackageId and actionKey but shows only a utility example for "nodes insert", so the placement of those fields inside "step" is inferred.
  • Only "workflows create" documents an id field in its response. The script reads .id from trigger and node responses too and stops if it is missing.
  • Package ids and action keys differ by workspace and depend on which integrations you have connected. Copy them from your catalog; this page does not guess them.
  • Step input mapping is dynamic per workspace. The CLI path is "nodes get" then "nodes update", where incomingEdges is a full replacement. The argument order for "nodes get" is inferred from "nodes update".
  • The help does not say whether step 1 connects to the trigger automatically. "clay workflows graph validate" reports a disconnected graph.
  • Calendly's no-show webhook sends a nested payload. A relay that flattens it to the sample fields keeps this workflow's inputs simple.
  • "runs test" without --live is assumed to run the draft. The reference lists --live without describing it.
  • Workflow runs can spend Clay credits and write to connected tools. Exit code 3 means re-run clay login, and exit code 4 means you are rate limited (wait for details.retryAfter).

Keep going

View all Inbound

Need help implementing a playbook?

Our team builds custom Clay workflows and AI automations for revenue teams.

Get it built for you