API Documentation
Use the Prospects API to send new prospects into CadenHQ from your app, forms, or integrations. Authenticate with an account API key; we upsert by email and start conversion campaigns for new prospects.
Overview
The CadenHQ API lets you submit prospects from outside the app (e.g. signup forms, landing pages, CRMs). Send a POST request with at least the prospect's email. We create or update the prospect by normalized email per account.
- New prospect – We set status to
new, start the conversion campaign, and schedule follow-up actions. - Existing prospect – We update any provided fields and return success without re-starting the campaign.
Base URL
All endpoints are relative to the base URL for your environment (e.g. https://api.cadenhq.com). Public API routes are under /api/v1 (e.g. POST /api/v1/prospects).
Authentication
Authenticate by sending your API key in the X-CadenHQ-Key header. Keys belong to your user and can be scoped to an account (e.g. one per environment).
Header
| Header | X-CadenHQ-Key |
|---|---|
| Description | Your API key (raw value). Keys belong to your user and can be scoped to an account; store them securely and never commit them to source control. |
If the key is missing or invalid, the API responds with 401 Unauthorized and a JSON body:
{"error":"Missing or invalid X-CadenHQ-Key"}Rate limits: Requests are limited per account (default 60 requests per minute). When exceeded, the API returns 429 Too Many Requests with a Retry-After header.
Getting an API key: Create keys in your CadenHQ dashboard under Account Settings → API Keys. The raw key is returned only once at creation; store it in your environment or secrets manager.
POST /api/v1/prospects
Create or update a prospect. The request body must include email. All other fields are optional. Prospects are upserted by (account_id, email_normalized); email is normalized (lowercased, trimmed). Metadata is not accepted for prospects created or updated via the API—including it returns 400 Bad Request.
Owner: The prospect owner is always set to the API key user; owner_id cannot be sent in the request.
Field limits: email 254 chars; display_name, first_name, last_name 255; phone 50; address 500; city, state, zip, country, source, external_id, UTM fields 255. campaign_id must be a valid UUID when provided.
Submit a prospect. New prospects are enrolled in the conversion campaign; existing prospects are updated with provided attributes.
Request headers
| Header | Required | Description |
|---|---|---|
X-CadenHQ-Key | Required | Account API key. |
Content-Type | Optional | Use application/json for JSON body. |
Request body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Required | Prospect email (max 254 chars). |
campaign_id | string (UUID) | Optional | Campaign ID to enroll the prospect in. |
display_name | string | Optional | Display name. |
first_name | string | Optional | First name. |
last_name | string | Optional | Last name. |
phone | string | Optional | Phone number (max 50 chars). |
address | string | Optional | Street address (max 500 chars). |
city | string | Optional | City (max 255 chars). |
state | string | Optional | State or region (max 255 chars). |
zip | string | Optional | Postal code (max 255 chars). |
country | string | Optional | Country (max 255 chars). |
source | string | Optional | Prospect source (e.g. landing_page, import). |
external_id | string | Optional | Your system's ID for this prospect. |
utm_source, utm_medium, etc. | string | Optional | UTM parameters (max 255 chars each). |
Responses
201 Created 200 OK 400 Bad Request 401 Unauthorized 404 Not Found 422 Unprocessable Entity 429 Too Many Requests201 Created – New prospect created. Body includes accepted: true, created: true, and prospect_id (CadenHQ UUID—use this for PATCH to update the prospect's status).
200 OK – Existing prospect updated. Body includes accepted: true, created: false, and prospect_id.
404 Not Found – campaign_id was provided but the campaign does not exist in the account.
PATCH /api/v1/prospects/:id
Update a prospect's status. The :id is the CadenHQ prospect UUID returned when you create the prospect (e.g. in prospect_id from POST /api/v1/prospects). Only prospects owned by the API key user can be updated; otherwise the API returns 404 Not Found. Setting status to converted, unsubscribed, or bounced removes the prospect from all campaigns.
:id — CadenHQ prospect UUID (returned as prospect_id in the create response).
Request headers
| Header | Required | Description |
|---|---|---|
X-CadenHQ-Key | Required | Account API key (prospect must be owned by this user). |
Content-Type | Optional | Use application/json for JSON body. |
Request body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | Required | One of new, converted, unsubscribed, bounced. |
Responses
200 OK 400 Bad Request 401 Unauthorized 404 Not Found200 OK — Status updated. Body includes accepted: true, prospect_id, status.
404 Not Found — No prospect found for the given UUID or the prospect is not owned by the API key user.
Errors
Error responses are JSON objects with error or errors fields.
400– Missing/invalid params, metadata not accepted401– Missing or invalid X-CadenHQ-Key404– Prospect not found (PATCH) or campaign not found (POST when campaign_id is provided)422– Validation failed429– Rate limit exceeded (see Retry-After header)
Code examples
cURL
curl -X POST https://api.cadenhq.com/api/v1/prospects \
-H "Content-Type: application/json" \
-H "X-CadenHQ-Key: YOUR_API_KEY" \
-d '{
"email": "prospect@example.com",
"display_name": "Jane Doe",
"source": "landing_page"
}'JavaScript (fetch)
const response = await fetch("https://api.cadenhq.com/api/v1/prospects", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CadenHQ-Key": process.env.CADENHQ_API_KEY,
},
body: JSON.stringify({
email: "prospect@example.com",
display_name: "Jane Doe",
source: "landing_page",
}),
});