Prerequisites
- A Text account with API access permission.
- A HubSpot account with permission to create and install an app.
- Docker with Docker Compose v2.
cloudflaredto expose the local service through a Cloudflare Quick Tunnel. You don’t need it if the service already has a public HTTPS address.- Git to clone the sample repository.
livechat/text-hubspot-contact-integration
Loading repository data...
Set up the integration
This guide runs a webhook service between Text and HubSpot. When a conversation closes, Text sends achat_deactivated webhook. The service retrieves the customer and Text-generated summary, creates or updates the matching HubSpot contact by email, then adds the summary to its timeline.
1
Create the Text API access
In Text, go to Settings → API access → Personal access tokens. Create a personal access token with the following scopes:
chats--all:rw— to read chats and request summaries in any group, orchats--access:rwto limit access to groups that the token owner is a member of.customers:ro— to read the customer’s email and name.webhooks.configuration:rw— to register the webhook.
account_id:personal_access_token.Go to Settings → API access → OAuth clients, create an OAuth client for the integration, and copy its client ID. You will register the webhooks for this OAuth client.The personal access token authorizes the Text API calls used by the service and webhook setup. The OAuth client ID identifies the integration that owns the registered webhook.2
Create the HubSpot API access
Follow HubSpot’s app creation guide to create and upload an app. Choose private distribution and static authentication, then configure these scopes:
crm.objects.contacts.readto find a contact by email.crm.objects.contacts.writeto create or update the contact.crm.objects.notes.writeto create the associated note.
HUBSPOT_ACCESS_TOKEN when configuring the service.Static authentication connects the sample to one HubSpot account. Use OAuth instead when your app needs to connect multiple HubSpot accounts.The service uses the HubSpot contacts API for contact management and the HubSpot notes API to add summaries to contact timelines.3
Clone and configure the service
Clone the repository and enter its directory:Create a Generate a webhook secret with a command such as:Set the generated value as The command prints a temporary
.env file with the following values:TEXT_WEBHOOK_SECRET.The service listens locally at http://localhost:8080, but Text needs a public HTTPS address to deliver webhook events. For local testing, a free Cloudflare Quick Tunnel gives the local service a temporary public address.To start the tunnel, run cloudflared in a separate terminal:https://<random-name>.trycloudflare.com address. Keep the tunnel running while you test. If its address changes after you register the webhook, unregister the old webhook before registering it again.Set WEBHOOK_PUBLIC_URL to the tunnel address without a trailing slash. For a deployed service, skip the tunnel and use the service’s public HTTPS address instead.The repository excludes .env from Git. Keep the file private because it contains credentials for both systems.4
Register the Text webhook
Load the values from Register a license-level The response contains the webhook ID.Run the registration once. To check the registrations owned by a specific OAuth client ID, use List webhooks.
.env into your terminal session:chat_deactivated webhook with the register_webhook method:5
Start the service
Build and start the container:Confirm that the service is healthy:A healthy service returns HTTP
204.Follow its logs while you test the integration:6
Verify the HubSpot contact and note
The service matches HubSpot contacts by customer email and skips chats without one. It maps the Text customer name to HubSpot
firstname and lastname by splitting at the first whitespace.To test the service, start a chat as a customer with an email address, exchange at least one message, then close the chat.The service log should contain synced Text chat with the Text chat ID, thread ID, and HubSpot contact ID. In HubSpot, open the contact with the same email address. Its activity timeline should contain a note with the summary title and bullet points and the chat details.Troubleshooting
Prepare the design for production
The sample demonstrates the integration flow, but it does not protect every sync from service restarts, temporary API failures, or repeated webhook deliveries. Before deploying the service, adapt the sample in three areas.Make sync delivery reliable
Make sync delivery reliable
The sample confirms receipt of a webhook before the sync finishes. It does not
save unfinished work or remember which threads it has processed, so a restart
can lose a sync and a repeated webhook can create a duplicate note.Before deploying:
- Save each sync job in a durable queue before confirming receipt of the webhook.
- Retry temporary Text and HubSpot failures, and alert your team when a job still fails.
- Record processed Text thread IDs so repeated webhook deliveries do not create another note.
- Continue delayed summary work after receiving the
thread_summary_setwebhook instead of relying on the sample’s 60-second polling window.
Define how HubSpot contacts are updated
Define how HubSpot contacts are updated
The sample matches contacts by email, updates name fields from Text, and creates
one note for every closed thread. Those choices may not match how your team
manages customer records in HubSpot.Before deploying:
- Decide whether Text or HubSpot owns each contact field.
- Store a Text customer ID to HubSpot contact ID mapping if email addresses can change.
- Decide how to handle customers without an email address or with duplicate HubSpot contacts.
- Choose whether HubSpot receives one note per thread or one note per chat.
Protect customer data in both systems
Protect customer data in both systems
The sample exposes a webhook endpoint and copies customer identity and
conversation summaries from Text to HubSpot. It does not define how the copied
data is retained or deleted.Before deploying:
- Run the service behind a stable HTTPS endpoint with health checks and monitoring.
- Store credentials in a secrets manager and rotate the webhook secret.
- Copy only the customer data you need and restrict access to it.
- Define retention and deletion behavior for the copied data in both Text and HubSpot.