Opt-Ins & Submit API Reference
POST external lead submission data directly into Hermon, and query historical traffic records, UTM attributions, logs, and form submissions.
Date & Timezone Handling: All timestamps in responses are UTC, formatted as ISO 8601 (2026-01-15T10:30:00.000Z). Date-range filter parameters accept either YYYY-MM-DD (which expands to UTC day boundaries) or full ISO 8601 timestamps.
Both bounds are inclusive. Only created_at is filterable on the list endpoint (there is no updated_at on opt-ins).
Both bounds are inclusive. Only created_at is filterable on the list endpoint (there is no updated_at on opt-ins).
Submit Endpoint
POST/api/opt-in/submit
Headers
Content-Type:application/json
x-api-key:sk_live_your_key_here
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
| string | Required | Lead's email address | |
| first_name | string | Required | Lead's first name |
| source | string | Required | source must be one of: CALENDLY, MANUAL, TYPEFORM, WEBINAR, NEWSLETTER, LANDING_PAGE, OTHER |
| last_name | string | Optional | Lead's last name |
| phone_e164 | string | Optional | Phone in E.164 format (e.g. +14155552671) |
| phone_country | string | Optional | ISO country code. Required if phone_e164 provided |
| provider_form_id | string | Optional | Your form's unique identifier |
| provider_form_name | string | Optional | Your form's display name |
| external_reference | string | Optional | Your unique submission ID for idempotency |
| questions_answers | array | Optional | Q&A pairs from your form (max 50) |
| traffic | object | Optional | UTM parameters and referrer data |
questions_answers item
json
{
"question": "What is your biggest challenge?",
"answer": "Generating consistent leads",
"position": 0
}traffic object
json
{
"utm_source": "facebook",
"utm_medium": "paid",
"utm_campaign": "q1-coaching",
"utm_content": "video-ad-1",
"utm_term": "coaching program",
"referrer": "https://facebook.com",
"landing_page": "https://yoursite.com/apply"
}If traffic.utm_content starts with user_ (a Clerk user ID), Hermon automatically assigns that user as the setter on the lead. This enables automated setter attribution from ad tracking.
Submit Responses
201New lead created via opt-in
json
{
"status": "success",
"message": "Lead created via opt-in",
"data": {
"opt_in_id": "uuid",
"lead_id": "uuid",
"is_new_lead": true
}
}200Existing lead updated
json
{
"status": "success",
"message": "Opt-in recorded for existing lead",
"data": {
"opt_in_id": "uuid",
"lead_id": "uuid",
"is_new_lead": false
}
}401Missing or invalid API key
json
{
"status": "error",
"message": "Invalid or revoked API key"
}400Validation failure
json
{
"status": "error",
"message": "source must be one of: CALENDLY, MANUAL, TYPEFORM, WEBINAR, NEWSLETTER, LANDING_PAGE, OTHER",
}429Rate limit exceeded
json
{
"status": "error",
"message": "Too many requests"
}Idempotency
Pass external_reference with a unique ID from your system. If the same external_reference + source combination is submitted again, Hermon returns the existing opt-in record without creating a duplicate.
json
{
"email": "john@example.com",
"first_name": "John",
"source": "LANDING_PAGE",
"external_reference": "typeform-submission-abc123"
}List Opt-Ins Records
List Opt-Ins
Retrieve a paginated list of opt-ins. Results can be filtered by source, lead ID, and creation date.
GET/api/external/opt-ins
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | Page number for pagination. Default: 1 |
| limit | integer | Optional | Number of items per page. Default: 10, Max: 100 |
| source | string | Optional | Filter by opt-in source. See Opt-in Source Values. |
| lead_id | string (UUID) | Optional | UUID of a specific lead. Returns opt-ins linked to that lead. |
| created_from | string | Optional | Lower bound for created_at. Accepts YYYY-MM-DD or ISO 8601. |
| created_to | string | Optional | Upper bound for created_at. Accepts YYYY-MM-DD or ISO 8601. |
Code Examples
curl -X GET "https://api.hermon.io/api/external/opt-ins?page=1&limit=10&source=CALENDLY&lead_id=e799c30f-9da7-4fd7-9552-83b96a9bfac2" \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_your_key_here"Response Example
json
{
"success": true,
"message": "Opt-ins fetched successfully",
"data": [
{
"id": "optin_e5f6a7b8-c9d0-1234-efgh-345678901234",
"lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source": "TYPEFORM",
"provider_form_id": "form_abc123def456",
"provider_form_name": "Coaching Application Form",
"external_reference": "TYPEFORM-response-abc123",
"created_at": "2026-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}Get Opt-In Details
Fetch detailed information for a single opt-in submission record by its unique UUID.
GET/api/external/opt-ins/:id
Path Parameters
:idRequired. The unique opt-in UUID.
Opt-In Object Fields
| Field | Type | Description |
|---|---|---|
| id | string (UUID) | Unique identifier for the opt-in. |
| lead_id | string (UUID) | ID of the lead this opt-in created or matched. |
| source | string (enum) | The system or integration that captured the opt-in. See Opt-in Source Values. |
| provider_form_id | string | null | The form's identifier in the originating provider (e.g. Typeform form ID). null for manual entries. |
| provider_form_name | string | null | The form's display name in the originating provider. null for manual entries. |
| external_reference | string | null | The provider's unique reference for this specific submission (e.g. Typeform response ID). |
| created_at | string (ISO 8601) | UTC timestamp when the opt-in was captured. |
| question_answers | array | Ordered list of form question/answer pairs. See Question Answer Object [Details API Only]. |
| traffic_attribution | object | UTM and referrer data. See Traffic Attribution Object [Details API Only]. |
Code Examples
curl -X GET "https://api.hermon.io/api/external/opt-ins/522b1759-d354-472c-8fb2-1a9bbc69eb9b" \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_your_key_here"Response Example
json
{
"success": true,
"message": "Opt-in fetched successfully",
"data": {
"id": "optin_e5f6a7b8-c9d0-1234-efgh-345678901234",
"lead_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source": "TYPEFORM",
"provider_form_id": "form_abc123def456",
"provider_form_name": "Coaching Application Form",
"external_reference": "TYPEFORM-response-abc123",
"created_at": "2026-01-15T10:30:00.000Z",
"question_answers": [
{
"id": "qa_001",
"question": "What is your biggest business challenge right now?",
"answer": "Struggling to convert leads into high-ticket clients consistently",
"position": 1
},
{
"id": "qa_002",
"question": "What is your monthly revenue?",
"answer": "$10,000 - $25,000",
"position": 2
},
{
"id": "qa_003",
"question": "How did you hear about us?",
"answer": "Facebook Ad",
"position": 3
}
],
"traffic_attribution": {
"utm_source": "facebook",
"utm_medium": "paid_social",
"utm_campaign": "q1-2026-coaching",
"utm_content": "video-ad-v2",
"utm_term": null,
"referrer": "https://www.facebook.com/",
"landing_page": "https://example.com/apply"
}
}
}Values Reference
Opt-in Source Values
| Value | Description |
|---|---|
| CALENDLY | Calendly form/event |
| ICLOSED | iClosed integration |
| GOHIGHLEVEL | GoHighLevel form |
| MANUAL | Manually created |
| TYPEFORM | Typeform submission |
| WEBINAR | Webinar registration |
| NEWSLETTER | Newsletter signup |
| LANDING_PAGE | Landing page form |
| OTHER | Other source |
Nested Objects Reference
Question Answer Object Fields
| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier for this question/answer pair. |
| question | string | The form question text. |
| answer | string | null | The respondent's answer. null if the question was skipped. |
| position | integer | Display order (1-indexed). |
Traffic Attribution Object Fields
| Field | Type | Description |
|---|---|---|
| utm_source | string | null | UTM source (e.g. "facebook", "google"). |
| utm_medium | string | null | UTM medium (e.g. "paid_social", "email"). |
| utm_campaign | string | null | UTM campaign name. |
| utm_content | string | null | UTM content variant. |
| utm_term | string | null | UTM keyword term. |
| referrer | string | null | HTTP referrer URL (the page that linked to the form). |
| landing_page | string | null | URL of the landing page the visitor was on when they submitted the form. |
Management Errors
401Missing or invalid API key
json
{
"status": "error",
"message": "Invalid or revoked API key"
}404Resource not found
json
{
"status": "error",
"message": "Resource not found"
}429Rate limit exceeded
json
{
"status": "error",
"message": "Too many requests"
}