This guide walks you through setting up a HubSpot workflow that automatically triggers an outbound AI Voice Agent call. To bring this to life, we will be using the following use case: triggering a call seven days before a client appointment. The AI agent will confirm attendance, answer basic questions about the appointment, and capture any rescheduling or cancellation preferences.
How it Works
Regardless of the use case, this is the core of how the automation is triggered:
Record meets enrolment criteria via HubSpot property value → enrols in workflow → workflow sends context payload to AI Voice Agent → AI Voice Agent launches outbound call to record
This foundation can be adapted to suit virtually any use case.
Focusing on our appointment reminder use case, here is a typical call flow once the record has passed through the workflow and the call has been triggered:
- The agent greets the customer by name and confirms their appointment date and time.
- It asks whether they are still happy to go ahead.
- If YES: it confirms any relevant details (location, who they’ll meet) and closes the call.
- If they want to RESCHEDULE: the agent asks for their preferred new date and advises that someone will follow up to confirm.*
- If they want to CANCEL: the agent notes this and advises the team will be in touch.
- If they ask a question the agent cannot answer: it tells them a team member will call back.
* NOTE: HubSpot AI Actions for meetingAvailability and bookMeeting are coming soon, enabling agents to reschedule meetings automatically without human intervention.
Assumptions
This guide assumes the following are already in place:
- You have created an outbound AI Voice Agent configured for the appointment reminder use case in the Aircall Dashboard.
- You have a HubSpot contact property that stores the appointment date.
Customising for Your Use Case
Before you begin, consider the following:
- Required fields: Contact phone number and appointment date are the minimum needed to trigger a call. All other fields are optional, only include what your AI agent actually uses during the conversation.
- Optional fields: You can add or remove context fields (e.g. location, assigned representative, appointment type) depending on what information your agent needs to handle the call effectively.
- Time frame: this workflow is based on 7 day reminders. You can adjust this to however many days align with your operations.
- Other record types: This guide is built around HubSpot Contact records, but the same approach can be adapted to work with other objects, simply swap the record type and associated properties in the workflow trigger and code action.
- Property names: Replace every placeholder like [your_appointment_date_property] with the actual internal name of the HubSpot property you use to store that data.
Step 1: Gather Your Credentials
You’ll be working across two tools - HubSpot and Aircall - so before you start, make sure you have access and are logged in to both. You will need to retrieve the following credentials from the Aircall Dashboard:
- AI Voice Agent ID
- Basic Auth token
You’ll need to paste these into the code in Step 2, and it saves time to have them on hand before you start building.
Your AI Voice Agent has a unique webhook URL that works as its identifier. This is available in the Aircall Dashboard for you to copy and use in your workflow.
Navigate to AI Voice Agent → Outbound call workflow → Webhook URL → Copy
Your Basic Auth token is used to authenticate requests from HubSpot to the Aircall API, verifying that the call was triggered by your workflow. It is generated from your Aircall API ID and API token, which you can find in the Aircall Dashboard by navigating to:
Integrations & API → API keys.
Once you have both values, combine them in the format API_ID:API_TOKEN and encode the result in Base64. This encoded string is your Basic Auth token.
Step 2: Create a Custom Code Action in HubSpot
In HubSpot, navigate to Automation > Workflows and create a new Contact-based workflow. Give it a descriptive name such as Appointment Reminder — Aircall Outbound Call.
Set the Enrollment Trigger
Use a schedule-based trigger tied to your appointment date property:
| Setting | Value |
| Trigger Type | On a schedule |
| Enroll | Contact |
| Frequency | Once |
| Date | [Your appointment date property, e.g. appointment_date] → Before Date → Days before date = 7 |
| Time of Day [Run time] | Choose a window appropriate for your business hours (e.g. 9am–5pm) |
The date-based trigger controls when the call fires, but it won't do anything unless contacts are actually enrolled in the workflow. The simplest and most universally applicable approach is to enrol contacts when their appointment date becomes known — i.e. when the property changes from empty to having a value.
To set this up, add a condition to the enrollment trigger:
Contact property → [your appointment date property] → is known.
This way, whenever an appointment date is set on a contact (regardless of how it got there) they'll be enrolled and the workflow will handle the rest when it’s 7 days before the appointment date stored on the property.
Leave re-enrolment turned on. If a contact reschedules and their appointment date is updated, they'll be enrolled again and receive a reminder call for the new date, which is the intended behaviour.
Click save, and your trigger is now complete.
Add a Custom Code Action
Inside the workflow, add an action and select Custom code. Choose Node.js 18.x as the language.
Under ‘Property to include in code’, add the HubSpot properties you want to pass to the AI Voice Agent. The table below shows the recommended fields, what they map to in the code, and guidance on which property to use:
| HubSpot Property | Variable Name in Code | What to put here |
| [First name property] | firstname | The property storing the contact’s first name (typically firstname in HubSpot) |
| [Last name property] | lastname | The property storing the contact’s last name (typically lastname) |
| [Phone number property] | phone | The mobile or primary phone number to call, in E.164 format (e.g. +447911123456). Use the property your team stores verified call numbers in. |
| [Appointment date property] | appointment_date | The property where you store the appointment date. This is the same one used in the enrollment trigger. |
| [Appointment time property] (optional) | appointment_time | The property storing the time of the appointment, if you store this separately from the date. |
| [Location property] (optional) | appointment_location | The address or location of the appointment, e.g. a clinic address, office, or branch name. |
| [Assigned rep property] (optional) | assigned_rep | The name of the person or team member the customer will meet. Use whichever property stores this in your CRM. |
Add or remove rows based on what context your AI agent needs. Only include fields the agent will actually reference during the call.
Paste the Code
Replace the default code with the following.
Please note:
- The event.inputFields rows in the code must correspond to the input fields you just configured above under ‘Property to include in code’. Ensure they also match in the context payload rows further down the code.
- Update the placeholder basicAuth with your Basic Auth token
- Update the placeholder agent URL with your agent ID/webhook URL
const axios = require('axios');
exports.main = async (event, callback) => {
const firstname = event.inputFields['firstname'];
const lastname = event.inputFields['lastname'];
const phone = event.inputFields['phone'];
const appt_date = event.inputFields['appointment_date'];
const appt_time = event.inputFields['appointment_time'];
const appt_address = event.inputFields['appointment_address'];
const legal_rep = event.inputFields['legal_representative'];
const basicAuth = 'YOUR_AIRCALL_BASIC_AUTH_TOKEN';
const agentUrl = 'https://api.aircall.io/v1/outbound-calls/agents/YOUR_AGENT_ID';
try {
const response = await axios.post(
agentUrl,
{
contact_phone: phone,
idempotency_key: `appt-reminder-${event.object.objectId}`,
context: {
first_name: firstname,
last_name: lastname,
appointment_date: appt_date,
appointment_time: appt_time,
appointment_address: appt_address,
legal_representative: legal_rep
},
expiration_seconds: 3600
},
{
headers: {
Authorization: `Basic ${basicAuth}`,
'Content-Type': 'application/json'
}
}
);
callback({ outputFields: { status: response.status, message: 'Call triggered' } });
} catch (error) {
const status = error.response?.status || 500;
const body = JSON.stringify(error.response?.data) || 'No response';
callback({ outputFields: { status, message: `${error.message} | ${body}` } });
}
};
Important: The agent will only use what is passed in the context payload. If a field is missing or blank, it will not reference it. Never pass a field with placeholder or test data in a live workflow.
Your workflow configuration is now complete.
Step 3: Testing Before Go-Live
Before enabling the workflow for all contacts, follow these steps:
- Enrol one internal test contact with a real mobile number and a dummy appointment date set to tomorrow.
- Trigger the workflow manually using the Test action in HubSpot.
- Listen to the call and verify the agent reads the correct name, date, time, and any other fields you included.
- Test the reschedule path by responding that you want to change the date.
Once you are satisfied it is performing as expected, you can turn on the workflow.
Tip: Use HubSpot’s workflow history view to check whether each code action succeeded or failed, and what status code Aircall returned. A 200 status means the call was triggered successfully.