Overview
UpSmith accepts leads from any tool that can send an HTTP request — a CRM, a lead provider, or your own backend. You map your fields into a small canonical shape, POST them to a private URL, and each lead flows straight into UpSmith and triggers your configured lead follow-up.
Every connection uses the same request format documented here. When you set up a connection, UpSmith gives you a source identifier and a webhook URL — the only per-connection difference is that URL. You (or your provider) configure your tool to POST to it.
Before you start
You need two things, both from the integration card in UpSmith:
- A Webhook URL — unique to your organization and the source.
- An API key — shown once when you create the connection.
Get your credentials
The request
Send a single JSON object per lead as an HTTP POST.
- Method:
POST - URL:
https://app.upsmith.com/webhook/{source}/{key}—sourceandkeyare strings UpSmith provides for your connection. Always copy the exact URL from your integration card rather than building it by hand. - Headers:
Content-Type: application/jsonandx-api-key: YOUR_API_KEY - Body: a JSON object using the fields below.
Keep the URL and key private
Payload fields
external_id is the only required field. Everything else is optional — send what you have, though a phone is strongly recommended so UpSmith can engage the lead over SMS. Any extra keys you include are preserved on the lead, so it's safe to pass through additional context.
| Field | Required | Description |
|---|---|---|
external_id | Yes | A stable, unique id for the lead from your system. Used to deduplicate — sending the same external_id twice will not create a second lead. |
lead_source | No | Free-text label for where the lead came from (e.g. "Facebook Ad"). Stored as a sub-source so leads stay distinguishable by origin. |
brand_name | No | Plain-text business name the agent should use for this lead. This is the highest-priority name for the lead. Use it when one webhook connection delivers leads for multiple brands; otherwise omit it to use the campaign or existing organization/contact fallback. |
name | No | Full name. Alternatively send first_name and last_name and we compose them. |
phone | No | Lead's phone number, ideally E.164 (+15125550142). Optional, but strongly recommended — it's how UpSmith engages the customer over SMS. |
email | No | Lead's email address. |
address | No | Street address. |
city | No | City. |
state | No | State / region. |
zip_code | No | Postal code. |
message | No | The lead's note or inquiry text. Read into the agent's first message so it can open with the customer's actual request instead of asking again. |
additional_details | No | Extra free-text the customer provided beyond the main message (e.g. a longer description). Combined with message into the agent's opening context. |
details | No | Alias for additional_details — free-text folded into the agent's opening context. |
notes | No | Any additional notes about the request. Folded into the agent's opening context. |
description | No | A description of the job or request. Folded into the agent's opening context. |
ad_name | No | Name of the ad the lead came from. Recorded for attribution. |
campaign_name | No | Name of the campaign the lead came from. Recorded for attribution. |
utm_source, utm_medium, utm_campaign, utm_term, utm_content | No | Standard UTM parameters. Recorded for attribution. |
referrer | No | Referring URL. Recorded for attribution. |
source_url | No | Landing-page URL the lead submitted from. Recorded for attribution. |
How the agent chooses the business name
For a lead-based campaign, UpSmith chooses one business name before the agent starts the conversation. It uses the first non-empty value in this order:
- Lead brand. For this webhook, that is the optional
brand_namein the POST body. Google LSA, Meta, Thumbtack, and Angi can set it on their connection in UpSmith. - Campaign name. The campaign's configured
organization_name. - Existing organization/contact fallback. UpSmith uses its existing contact-based brand routing when available, then the organization's alias or name.
These values do not conflict or get combined: the first available value wins. A blank connection or payload brand simply moves to the next step. If your organization has one business name, you can leave the lead brand blank and rely on the campaign or organization default.
| Lead brand | Campaign name | Name the agent uses |
|---|---|---|
| Austin Water Heaters | Home Services | Austin Water Heaters |
| Not provided | Home Services | Home Services |
| Not provided | Not provided | Existing contact brand, or the organization alias/name |
Campaign name vs. campaign_name
campaign_name field is marketing attribution only. It does not control the business name the agent says. Use brand_name for a per-lead business name.Example
curl -X POST "https://app.upsmith.com/webhook/<source>/<key>" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"external_id": "lead-12345",
"lead_source": "Facebook Ad",
"brand_name": "Austin Water Heaters",
"name": "Jane Doe",
"phone": "+15125550142",
"email": "jane@example.com",
"address": "123 Main St",
"city": "Austin",
"state": "TX",
"zip_code": "78701",
"message": "Need a quote to replace my water heater."
}'200 OK
{ "status": "success" }Responses & errors
| Status | Meaning |
|---|---|
200 | Lead accepted ({"status":"success"}). Also returned for an unrecognized URL, so a wrong key fails quietly rather than erroring. |
401 | Missing or invalid API key. Check the x-api-key header. |
422 | Payload rejected — for example, external_id is missing or brand_name is not valid plain text. |
500 | Something failed on our side. Safe to retry. |
Troubleshooting
- Leads aren't showing up. Confirm the connection is Active on the Integrations card and that Lead follow-up is configured. The card shows the last webhook it received.
- Getting a 401. The
x-api-keyheader is missing or wrong. Rotate the key on the card and update it in your tool. - Getting a 422. The payload is missing
external_idor isn't valid JSON, orbrand_nameis not valid plain text. - Everything returns 200 but no lead. A 200 on an unknown URL is expected — double check you're POSTing to the exact URL from your card.
Need help?
Questions, or something not working the way you expect? Email eng@upsmith.com and we'll help you get set up.