Introduction
TextConvo provides a suite of APIs to ingest leads, send SMS messages, receive replies, and automate conversations using AI-powered workflows.
Base URL
https://api.textconvo.aiQuick Start
Try your first API call right away. Replace YOUR_API_KEY with your actual key.
curl -X POST https://api.textconvo.ai/functions/v1/ingest-lead \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"first_name": "John",
"last_name": "Doe",
"phone": "+15035551234",
"email": "john@example.com"
}'Authentication
All API requests must include your API key in the request headers.
Required Header
X-API-Key: YOUR_API_KEYPOST /functions/v1/ingest-lead
Content-Type: application/json
X-API-Key: YOUR_API_KEYHMAC Authentication
TextConvo supports optional HMAC request signing for enhanced security. This ensures requests are not tampered with in transit.
Steps
- Generate a Unix timestamp.
- Create a signature using HMAC SHA-256 with your API secret.
- Send the signature in request headers.
Required Headers
X-API-KeyX-TimestampX-SignatureSignature Formula
HMAC_SHA256(
timestamp + request_body,
API_SECRET
)Example Request
curl -X POST https://api.textconvo.ai/functions/v1/ingest-lead \
-H "Content-Type: application/json" \
-H "X-API-Key: tc_live_xxxxx" \
-H "X-Timestamp: 1710000000" \
-H "X-Signature: generated_signature" \
-d '{
"first_name": "John",
"phone": "+15035551234"
}'Note: HMAC signing is recommended for enterprise integrations.
Lead Ingestion API
/functions/v1/ingest-leadCreate a new lead inside TextConvo. The lead will be matched to an existing contact by phone number or created as a new contact. A journey will be queued automatically based on your account configuration.
Request Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | Your TextConvo API key |
Content-Type | Yes | application/json |
X-Timestamp | No | Unix timestamp for HMAC |
X-Signature | No | HMAC-SHA256 signature |
Request Body
{
"lead_external_id": "string — your CRM's ID for this lead",
"first_name": "string",
"last_name": "string",
"email": "string",
"phone": "string — E.164 format e.g. +15035551234",
"company": "string (optional)",
"lead_source": "string (optional)",
"custom_fields": {
"any_key": "any_value"
}
}Required fields: phone is required.
Success Response
{
"success": true,
"lead_id": "lead_abc123",
"contact_id": "cnt_xyz789",
"status": "queued"
}Error Response
{
"success": false,
"error": "phone is required",
"code": "MISSING_REQUIRED_FIELD"
}Contacts API
/functions/v1/contacts/{contact_id}Retrieve a contact and their latest inquiry by contact ID.
Example Request
curl -X GET https://api.textconvo.ai/functions/v1/contacts/cnt_xyz789 \
-H "X-API-Key: YOUR_API_KEY"Response
{
"contact_id": "cnt_xyz789",
"phone": "+15035551234",
"email": "john@example.com",
"created_at": "2026-04-20T10:00:00Z",
"latest_inquiry": {
"id": "inq_abc123",
"lead_source": "hubspot",
"created_at": "2026-04-20T10:00:00Z",
"status": "completed"
}
}Webhooks
TextConvo can send webhook events when SMS activity occurs.
Supported Events
sms.delivered— Message delivered to carriersms.failed— Message failed to deliversms.reply— Contact replied to a messagejourney.started— Journey began for a contactjourney.completed— Journey finishedjourney.opted_out— Contact opted outcontact.created— New contact created
Payload Structures
sms.delivered
{
"event": "sms.delivered",
"message_id": "msg_abc123",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"phone": "+15035551234",
"provider": "twilio",
"delivered_at": "2026-04-20T10:12:00Z"
}sms.failed
{
"event": "sms.failed",
"message_id": "msg_abc123",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"phone": "+15035551234",
"error": "carrier_rejected",
"failed_at": "2026-04-20T10:12:00Z"
}sms.reply
{
"event": "sms.reply",
"message_id": "msg_reply123",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"phone": "+15035551234",
"message": "Yes send quote",
"received_at": "2026-04-20T10:18:00Z"
}journey.started
{
"event": "journey.started",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"journey_queue_id": "jq_def456",
"started_at": "2026-04-20T10:00:00Z",
"metadata": {
"lead_source": "hubspot",
"entry_step": "initial_outreach"
}
}journey.completed
{
"event": "journey.completed",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"journey_queue_id": "jq_def456",
"outcome": "completed",
"completed_at": "2026-04-20T11:30:00Z",
"metadata": {
"messages_sent": 3,
"replies_received": 2,
"duration_minutes": 45
}
}journey.opted_out
{
"event": "journey.opted_out",
"contact_id": "cnt_xyz789",
"lead_id": "lead_abc123",
"journey_queue_id": "jq_def456",
"opted_out_at": "2026-04-20T10:25:00Z",
"metadata": {
"keyword": "STOP",
"channel": "sms"
}
}contact.created
{
"event": "contact.created",
"contact_id": "cnt_xyz789",
"phone": "+15035551234",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"created_at": "2026-04-20T10:00:00Z"
}Webhook Security
All webhooks from TextConvo include an X-TextConvo-Signature header. Verify it using HMAC-SHA256 with your webhook secret.
const crypto = require('crypto');
const signature = req.headers['x-textconvo-signature'];
const computed = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
const isValid = signature === computed;Rate Limits
| Plan | Requests per minute | Daily limit |
|---|---|---|
| Starter | 60 | 10,000 |
| Professional | 300 | 100,000 |
| Enterprise | Custom | Unlimited |
Response Headers
Rate limit headers are returned on every response.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1714000000Limit Exceeded
When exceeded, TextConvo returns 429.
{
"error": "Rate limit exceeded",
"retry_after": 30
}Error Codes
| Code | Description |
|---|---|
400 | Bad Request — Invalid parameters |
401 | Unauthorized — Invalid API key |
403 | Forbidden — Insufficient permissions |
429 | Rate Limit — Too many requests |
500 | Server Error — Internal error |
CRM Integrations
Overview
TextConvo supports bi-directional CRM integration. Your CRM sends leads via webhook, TextConvo runs the journey, and pushes results back automatically.
CRM → Webhook → TextConvo → Journey → Push results back → CRMHubSpot Integration Guide
Prerequisites
- HubSpot account (any paid plan)
- TextConvo account with API access
- Super Admin access in HubSpot
Step 1 — Create a Legacy App in HubSpot
- Go to app-na2.hubspot.com
- Click Settings (gear icon) → Integrations → Legacy Apps
- Click "Create legacy app" → Select "Private"
- Name it "TextConvo"
- Go to Scopes tab and add crm.objects.contacts.read and crm.objects.contacts.write
- Click "Create app"
- Go to Auth tab → click "Show token"
- Copy your Access Token (starts with pat-)
Step 2 — Create custom contact properties
In HubSpot → Settings → Data Management → Properties → Contact properties → Create property:
| Property label | Internal name | Field type |
|---|---|---|
| TextConvo Journey Status | textconvo_journey_status | Single-line text |
| TextConvo Journey Date | textconvo_journey_date | Date picker |
| TextConvo Outcome | textconvo_outcome | Single-line text |
| TextConvo Notes | textconvo_notes | Multi-line text |
Step 3 — Connect in TextConvo
- Go to Integrations → CRM Connectors → HubSpot
- Click "Connect"
- Paste your Access Token (pat-na2-...)
- Paste your Webhook Client Secret (found in HubSpot → Settings → Integrations → Private Apps → your app → Auth tab → Client Secret)
- Review field mappings (defaults are recommended)
- Select outbound events to sync back
- Click "Save & Activate"
Step 4 — Configure HubSpot webhook
- In your HubSpot app → Webhooks tab
- Set Target URL to your TextConvo webhook URL:
- In TextConvo → Integrations → CRM Connectors → HubSpot → Manage
- Copy the Webhook URL shown at the top
- Paste it into HubSpot as the Target URL
- Subscribe to Contact → Created and Contact → Property changed events
- Include properties: firstname, lastname, phone, email, company
- Click Subscribe
Step 5 — Test the integration
- Create a test contact in HubSpot with a phone number
- Check TextConvo → Integrations → HubSpot → Webhook logs
- Verify contact appears in TextConvo contacts
- Check HubSpot contact for TextConvo properties after journey completes
Field Mapping Reference
| HubSpot field | TextConvo field |
|---|---|
firstname | first_name |
lastname | last_name |
phone | phone (required) |
email | |
company | company |
hs_lead_source | lead_source |
Troubleshooting
| Issue | Solution |
|---|---|
| Webhook logs show “Invalid signature” | Check Client Secret is correct in TextConvo |
| Contact created but no journey | Phone number missing on HubSpot contact |
| Push fails with 400 | Custom HubSpot properties not created (Step 2) |
| Push fails with 401 | Access Token expired — reconnect in TextConvo |
HubSpot Integration FAQ
GoHighLevel Integration Guide
Prerequisites
- GoHighLevel account (any Agency plan)
- TextConvo account with API access
- Super Admin access in TextConvo
Step 1 — Create a Private Integration Token in GHL
- Log into GHL and switch to your Sub-Account
- Go to Settings → Private Integrations → Create New Integration
- Name it "TextConvo"
- Select these scopes:
contacts.readonlycontacts.writelocations.readonly
- Click Create and copy the token immediately (starts with
pit-)
You cannot view this token again after leaving the page.
Step 2 — Find your Location ID
- In GHL, switch to your Sub-Account
- Look at the URL in your browser:
app.gohighlevel.com/location/{YOUR_LOCATION_ID}/dashboardCopy the Location ID from the URL.
Step 3 — Create custom contact fields in GHL
In GHL → Settings → Custom Fields → Add Field (type: Text) for each:
| Field Key | Purpose |
|---|---|
textconvo_journey_status | Journey completion status |
textconvo_journey_outcome | Journey outcome (qualified, not interested etc) |
textconvo_reentry_token | Triggers re-entry into a new journey |
Step 4 — Connect in TextConvo
- Go to Integrations → CRM Connectors → GoHighLevel
- Click "Connect"
- Select your Account
- Paste your Private Integration Token (pit-xxx)
- Paste your Sub-Account Location ID
- Review field mappings (defaults recommended)
- Select outbound events to sync back
- Click "Save & Activate"
Step 5 — Set up TWO GHL Workflows
GHL uses Workflows to send webhooks. You need two separate workflows.
Get your Webhook URL first: TextConvo → Integrations → CRM Connectors → GoHighLevel → Manage → copy the Webhook URL.
Workflow 1 — New Contacts
- GHL → Automation → Workflows → Create Workflow → Start from Scratch
- Add Trigger: Contact Created (no filters needed)
- Add Action: Webhook
- Method: POST
- URL: paste your TextConvo Webhook URL copied above
- Save and click Publish
Workflow 2 — Contact Updates
- GHL → Automation → Workflows → Create Workflow → Start from Scratch
- Add Trigger: Contact Changed (no filters needed)
- Add Action: Webhook
- Method: POST
- URL: paste the same TextConvo Webhook URL
- Save and click Publish
Step 6 — Test the integration
- Create a test contact in GHL with a phone number
- Check TextConvo → Inquiries — contact should appear within seconds with SOURCE = GoHighLevel
- Update a field on the GHL contact
- Check the Activity Timeline in TextConvo — should show "GoHighLevel contact updated" with the changed field
Field Mapping Reference
| GoHighLevel field | TextConvo field |
|---|---|
firstName | first_name |
lastName | last_name |
phone | phone (required) |
email | |
source | lead_source |
tags | tags |
Troubleshooting
| Issue | Solution |
|---|---|
| No contacts appearing after creation | Confirm Workflow 1 (Contact Created) is Published |
| No timeline events on field changes | Confirm Workflow 2 (Contact Changed) is Published |
| Test connection fails with 401 | Token invalid — recreate Private Integration in GHL |
| Test connection fails with 404 | Location ID incorrect — check URL in GHL sub-account |
| SOURCE shows as “gohighlevel” not “GoHighLevel” | Reconnect the integration — display name fix is live |
GoHighLevel Integration FAQ
Zoho CRM Integration Guide
Prerequisites
- Zoho CRM account (any paid plan)
- TextConvo account with API access
- Super Admin access in TextConvo
Step 1 — Generate an OAuth Access Token
For testing, use the Self Client method:
- Go to api-console.zoho.com
- Click "Self Client"
- Click "Generate Code"
- In the Scope field paste:text
ZohoCRM.modules.contacts.ALL,ZohoCRM.org.READ,ZohoCRM.modules.notes.CREATE - Set duration to 10 minutes
- Click Create — copy the token immediately (starts with
1000.)
For production use, create a Server-based OAuth app to get a refresh token that never expires. Self Client tokens expire in 10 minutes.
Step 2 — Connect in TextConvo
- Go to Integrations → CRM Connectors → Zoho CRM
- Click Connect
- Select your Account
- Paste your OAuth Access Token (starts with
1000.) - Enter any value for Webhook Secret (e.g.
test123) — optional for testing - Review field mappings (defaults recommended)
- Select outbound events to sync back
- Click Save & Activate
Get your Webhook URL from: TextConvo → Integrations → CRM Connectors → Zoho CRM → Manage → Webhook URL.
Step 3 — Create TWO Workflow Rules in Zoho CRM
Zoho sends webhooks via Workflow Rules. You need two separate rules.
Rule 1 — New Contacts
- Zoho CRM → Setup → Automation → Workflow Rules → Create Rule
- Module: Contacts
- Rule Name: TextConvo — Contact Created
- Execute On: Record Action → Create
- Condition: All Contacts → Done
- Instant Action: Webhook
- URL: paste your TextConvo Webhook URL
- Method: POST
- Body Type: Raw → Format: JSON
- Body:
{
"contact_id": "${!Contacts.id}",
"First_Name": "${!Contacts.First_Name}",
"Last_Name": "${!Contacts.Last_Name}",
"Phone": "${!Contacts.Phone}",
"Mobile": "${!Contacts.Mobile}",
"Email": "${!Contacts.Email}",
"operation": "insert"
}- Save and Associate → Activate the rule
Rule 2 — Contact Updates
- Create another Workflow Rule
- Module: Contacts
- Rule Name: TextConvo — Contact Updated
- Execute On: Record Action → Edit
- Condition: All Contacts → Done
- Instant Action: Webhook
- URL: same TextConvo Webhook URL
- Method: POST
- Body Type: Raw → Format: JSON
- Body:
{
"contact_id": "${!Contacts.id}",
"First_Name": "${!Contacts.First_Name}",
"Last_Name": "${!Contacts.Last_Name}",
"Phone": "${!Contacts.Phone}",
"Mobile": "${!Contacts.Mobile}",
"Email": "${!Contacts.Email}",
"operation": "update"
}- Save and Associate → Activate the rule
Important: The merge field syntax requires ${!Contacts.field_name} with the exclamation mark and underscores. Spaces in field names are not supported.
Step 4 — Create custom fields in Zoho for outbound sync
In Zoho CRM → Setup → Customization → Modules → Contacts → Fields → Add Custom Field (type: Single Line Text):
- Field name:
TextConvo_Journey_Status - Field name:
TextConvo_Journey_Outcome
Step 5 — Test the integration
- Create a new contact in Zoho CRM with a phone number (include country code e.g. +1)
- Check TextConvo → Inquiries — contact should appear within seconds with SOURCE = Zoho
- Edit a field on that same contact (e.g. change first name)
- Check the Activity Timeline in TextConvo — should show "Zoho contact updated" with the changed field
Field Mapping Reference
| Zoho CRM field | TextConvo field |
|---|---|
First_Name | first_name |
Last_Name | last_name |
Phone | phone (required) |
Email | |
Lead_Source | lead_source |
Important Notes
- OAuth tokens from Self Client expire in 10 minutes (testing only)
- For production, use a Server-based OAuth app to get a non-expiring refresh token
- Two workflow rules are required — one for Create, one for Edit
- Merge fields must use
${!Contacts.field_name}syntax with ! and underscores - Zoho limits webhooks to 10 fields maximum per notification
Troubleshooting
| Issue | Solution |
|---|---|
| No contacts appearing | Confirm Rule 1 (Create) is Active in Zoho |
| No timeline events on edits | Confirm Rule 2 (Edit) is Active and body has operation=update |
| Connection invalid after 10 min | OAuth token expired — regenerate from api-console.zoho.com |
| Duplicate inquiries on edit | Check Rule 2 body — operation must be "update" not "insert" |
| Merge field error on save | Use ${!Contacts.First_Name} syntax — exclamation mark required |
| Test connection fails 401 | Token expired — generate a new one from Self Client |
Zoho CRM Integration FAQ
Pipedrive
Coming soonDocumentation coming soon. Contact us to join the early access list.
Contact usZendesk
Coming soonDocumentation coming soon. Contact us to join the early access list.
Contact usSalesforce
Coming soonDocumentation coming soon. Contact us to join the early access list.
Contact usPush Journey Results
/functions/v1/push-hubspotManually trigger a journey result to be pushed back to HubSpot. This is called automatically by TextConvo when a journey completes, but can also be called manually.
Request Body
{
"contact_id": "cnt_xyz789",
"account_id": "uuid",
"outcome": "completed | opted_out | no_response",
"notes": "optional string"
}Response
{
"status": "success",
"hubspot_contact_id": "473031564003"
}