Leads API Reference

Fetch leads and query histories for contacts matching Hermon data records.

Date & Timezone Handling: All timestamps in responses are UTC, formatted as ISO 8601 (2026-01-15T10:30:00.000Z). Date-range filters accept either date-only YYYY-MM-DD (which expands to UTC day boundaries) or full ISO 8601 timestamps.
Rate Limiting: Requests are limited per organization (300 per minute, shared by all of its API keys). If exceeded, a 429 Too Many Requests error is returned with a Retry-After header giving the seconds to wait.

List Leads

Retrieve a paginated list of leads. Results can be filtered by source, status role, and assigned setter, closer, or triager, or searched by email or phone number.

GET/api/external/leads

Query Parameters

ParameterTypeRequiredDescription
pageintegerOptionalPage number for pagination. Default: 1
limitintegerOptionalNumber of items per page. Default: 10, Max: 100
searchstringOptionalFind a lead by email (case-insensitive substring) or phone number (notation-insensitive). See Search.
sourcestringOptionalFilter by lead source. See Lead Source Values.
status_rolestringOptionalComma-separated list of status roles. See Status Role Values.
setterstringOptionalEmail address of the setter to filter by.
triagerstringOptionalEmail address of the triager to filter by.
closerstringOptionalEmail address of the closer to filter by.
created_fromstringOptionalLower bound for created_at. Accepts YYYY-MM-DD or ISO 8601.
created_tostringOptionalUpper bound for created_at. Accepts YYYY-MM-DD or ISO 8601.
updated_fromstringOptionalLower bound for updated_from. Accepts YYYY-MM-DD or ISO 8601.
updated_atstringOptionalUpper bound for updated_at. Accepts YYYY-MM-DD or ISO 8601.

Search

Use searchto locate a specific lead by email or phone number — useful for resolving a lead's id before calling the detail, custom field, or status-update endpoints. It combines with the date-range filters and pagination, and a value that matches nothing returns an empty list.

Email — any value containing a non-phone character (a letter, @, ., etc.) is matched against the email, case-insensitively, as a substring. Both john and JOHN.DOE@example.com match john.doe@example.com.
Phone — a value made up only of digits, +, spaces, dashes, and parentheses is matched against the phone number. Leading zeros are ignored and local and international notations are treated as equivalent. For a lead stored as +31612345678, all of 0612345678, +31612345678, and 0031612345678 match. Name and custom-field matching are not supported.

Code Examples

curl -X GET "https://api.hermon.io/api/external/leads?page=1&limit=10&search=john.doe@example.com&source=LANDING_PAGE&status_role=NEW_LEAD&setter=sales-setter@mailinator.com&closer=hermon@mailinator.com&triager=triager@mailinator.com" \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_live_your_key_here"

Response Example

json
{
  "success": true,
  "message": "Leads fetched successfully",
  "data": [
    {
      "id": "e799c30f-9da7-4fd7-9552-83b96a9bfac2",
      "first_name": "John",
      "last_name": "Doe",
      "email": "john.doe@example.com",
      "phone_e164": "+14155551234",
      "phone_country": "US",
      "source": "LANDING_PAGE",
      "sales_status": {
        "id": "status_xyz123",
        "name": "New Lead",
        "role": "NEW_LEAD",
        "description": "Newly imported lead",
        "text_color": "#2563EB",
        "bg_color": "#DBEAFE"
      },
      "setter": null,
      "triager": null,
      "closer": null,
      "notes": [],
      "counts": {
        "notes": 0,
        "appointments": 1,
        "contracts": 0,
        "payments": 0,
        "opt_ins": 1,
        "deliveries": 0
      },
      "custom_fields": [
        {
          "id": "field_age",
          "name": "Age",
          "value": 30
        }
      ],
      "first_source": {
        "id": "src_fb",
        "name": "Facebook Ads"
      },
      "last_source": {
        "id": "src_fb",
        "name": "Facebook Ads"
      },
      "touch_points": [
        {
          "id": "6f1c2b9e-3d4a-4f8b-9c2e-1a7d5e3b8c40",
          "owner": {
            "id": "user_2abcSetter",
            "first_name": "Jane",
            "last_name": "Smith",
            "profile_image_url": null,
            "role": "org:sales_setter"
          },
          "owner_id": "user_2abcSetter",
          "type": "PHONE_CALL",
          "due_at": "2026-02-10T15:00:00.000Z",
          "has_time": true,
          "note": "Call back after budget approval",
          "created_at": "2026-02-08T10:30:00.000Z"
        }
      ],
      "created_at": "2026-02-08T10:00:00.000Z",
      "updated_at": "2026-02-08T10:30:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}

Get Lead Details

Fetch detailed information for a single lead by its unique UUID.

GET/api/external/leads/:id

Path Parameters

:idRequired. The unique lead UUID.

Lead Object Fields

FieldTypeDescription
idstring (UUID)Unique identifier for the lead.
first_namestringLead's first name.
last_namestringLead's last name.
emailstringLead's email address.
phone_e164string | nullPhone number in E.164 format.
phone_countrystring | nullISO 3166-1 alpha-2 country code derived from phone.
sourcestring (enum)Lead source (e.g. CALENDLY, TYPEFORM, WEB_FORM). See Lead Source Values.
sales_statusobjectCurrent status details. See Lead Status Object.
setterobject | nullAssigned setter. See Lead User Object.
triagerobject | nullAssigned triager. See Lead User Object.
closerobject | nullAssigned closer. See Lead User Object.
notesarrayLatest note(s) on the lead. See Lead Note Object.
countsobjectTotal count of related resources. See Lead Counts Object.
custom_fieldsarrayAssigned custom field values. See Lead Custom Field Object.
first_sourceobject | nullFirst marketing attribution source. See Lead Source Object.
last_sourceobject | nullLast marketing attribution source. See Lead Source Object.
touch_pointsarrayOpen next touchpoints on the lead, earliest due first. Each team member (setter, triager, closer, …) owns at most one. Empty when none are scheduled. See Lead Touch Point Object.
billing_detailsobject | nullBilling information. See Lead Billing Details Object [Details API Only].
created_atstring (ISO 8601)UTC timestamp of creation.
updated_atstring (ISO 8601)UTC timestamp of last update.

Code Examples

curl -X GET "https://api.hermon.io/api/external/leads/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": "Lead fetched successfully",
  "data": {
    "id": "e799c30f-9da7-4fd7-9552-83b96a9bfac2",
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com",
    "phone_e164": "+14155551234",
    "phone_country": "US",
    "source": "LANDING_PAGE",
    "sales_status": {
      "id": "status_xyz123",
      "name": "New Lead",
      "role": "NEW_LEAD",
      "description": "Newly imported lead",
      "text_color": "#2563EB",
      "bg_color": "#DBEAFE"
    },
    "setter": null,
    "triager": null,
    "closer": null,
    "notes": [],
    "counts": {
      "notes": 0,
      "appointments": 1,
      "contracts": 0,
      "payments": 0,
      "opt_ins": 1,
      "deliveries": 0
    },
    "custom_fields": [],
    "first_source": {
      "id": "src_fb",
      "name": "Facebook Ads"
    },
    "last_source": {
      "id": "src_fb",
      "name": "Facebook Ads"
    },
    "touch_points": [
      {
        "id": "6f1c2b9e-3d4a-4f8b-9c2e-1a7d5e3b8c40",
        "owner": {
          "id": "user_2abcSetter",
          "first_name": "Jane",
          "last_name": "Smith",
          "profile_image_url": null,
          "role": "org:sales_setter"
        },
        "owner_id": "user_2abcSetter",
        "type": "PHONE_CALL",
        "due_at": "2026-02-10T15:00:00.000Z",
        "has_time": true,
        "note": "Call back after budget approval",
        "created_at": "2026-02-08T10:30:00.000Z"
      }
    ],
    "billing_details": {
      "id": "bill_xyz123",
      "business_name": "Doe Coaching LLC",
      "address": "123 Main St",
      "city": "San Francisco",
      "zipcode": "94105",
      "province": "CA",
      "country": "US",
      "vat_number": null,
      "vat_exempt": false,
      "created_at": "2026-02-08T10:00:00.000Z",
      "updated_at": "2026-02-08T10:00:00.000Z"
    },
    "created_at": "2026-02-08T10:00:00.000Z",
    "updated_at": "2026-02-08T10:30:00.000Z"
  }
}

Update Lead Status

Update the status of a specific lead by providing a valid status UUID.

PATCH/api/external/leads/:id/status

Path Parameters

:idRequired. The unique lead UUID.

Headers

Content-Type:application/json
Reasons (Lost / Unqualified): when the target status has role LOST or UNQUALIFIED with reasons configured, you may record one with reason_id or reason_name — look them up via GET /api/external/statuses/:id/reasons. The reason is optional over the API and is validated and stored on the status-change record when provided.

Request Body Fields

FieldTypeRequiredDescription
status_idstring (UUID)RequiredThe unique UUID of the status to assign to the lead.
reason_idstring (UUID)OptionalReason to record for this change, by id. Only applies to statuses with role LOST or UNQUALIFIED. Must be an active reason configured on that status. Takes precedence when both reason_id and reason_name are sent.
reason_namestringOptionalReason to record for this change, matched case-insensitively against the status’s active reasons. Alternative to reason_id. Returns a validation error when no active reason with that name exists on the status.

Code Examples

curl -X PATCH "https://api.hermon.io/api/external/leads/24567881-3574-4aa9-82b2-d7837efa10e5/status" 
  -H "Content-Type: application/json" 
  -H "x-api-key: sk_live_your_key_here" 
  -d '{
    "status_id": "4bb2ae65-8ab1-4695-b896-190711a07cd0"
  }'

Response Example

json
{
  "success": true,
  "message": "Lead status updated successfully",
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": {
      "id": "status_xyz789",
      "name": "Follow-up Required",
      "role": "FOLLOW_UP"
    }
  }
}

Update Lead Assignments

Update a lead's ownership — its setter, closer, and/or triager — by passing any combination of the three roles. Only fields present in the request body are changed; omitted fields are left untouched, and passing nullclears (unassigns) that role. Each provided user is validated to be an active member of the same workspace. The change is attributed on the lead's activity timeline as an External update, and the same assignment notifications fire as from the dashboard.

PATCH/api/external/leads/:id/assignments
Resolving user IDs: Assignments require a Clerk user ID (e.g. user_2abc...). Call the GET /api/external/team-members endpoint to list active workspace users and look up the id to pass here.

Path Parameters

:idRequired. The unique lead UUID.

Headers

Content-Type:application/json

Request Body Fields

At least one of setter_id, closer_id, or triager_id must be present.

FieldTypeRequiredDescription
setter_idstring (Clerk user ID) | nullOptionalThe user to assign as setter. Pass a Clerk user ID (e.g. "user_2abc...") to assign, or null to unassign. Omit the field to leave the current setter unchanged.
closer_idstring (Clerk user ID) | nullOptionalThe user to assign as closer. Pass a Clerk user ID to assign, or null to unassign. Omit the field to leave the current closer unchanged.
triager_idstring (Clerk user ID) | nullOptionalThe user to assign as triager. Pass a Clerk user ID to assign, or null to unassign. Omit the field to leave the current triager unchanged.

Code Examples

curl -X PATCH "https://api.hermon.io/api/external/leads/24567881-3574-4aa9-82b2-d7837efa10e5/assignments" \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_live_your_key_here" \
  -d '{
    "setter_id": "user_2abc123def456",
    "closer_id": "user_2ghi789jkl012",
    "triager_id": null
  }'

Response Example

json
{
  "status": "success",
  "message": "Lead assignments updated successfully",
  "data": {
    "id": "24567881-3574-4aa9-82b2-d7837efa10e5"
  }
}

Add Lead Note

Attach a plain-text note to a specific lead. The note is stored on the lead's activity timeline with its source recorded as External (no individual user is attributed as the author).

POST/api/external/leads/:id/notes

Path Parameters

:idRequired. The unique lead UUID.

Headers

Content-Type:application/json

Request Body Fields

FieldTypeRequiredDescription
notestringRequiredThe note content to attach to the lead. Must be non-empty and at most 10,000 characters.

Code Examples

curl -X POST "https://api.hermon.io/api/external/leads/24567881-3574-4aa9-82b2-d7837efa10e5/notes"
  -H "Content-Type: application/json"
  -H "x-api-key: sk_live_your_key_here"
  -d '{
    "note": "Followed up by phone — lead requested a call back next week."
  }'

Response Example

json
{
  "status": "success",
  "message": "Note added successfully",
  "data": {
    "id": "f7c1a2b3-4d5e-6789-abcd-ef0123456789"
  }
}

Values Reference

Lead Source Values

ValueDescription
CALENDLYCalendly integration
ICLOSEDiClosed integration
GOHIGHLEVELGoHighLevel integration
MANUALManually created
TYPEFORMTypeform integration
WEBINARWebinar signup
NEWSLETTERNewsletter subscription
LANDING_PAGELanding page submission
OTHEROther source

Status Role Values

ValueDescription
NEW_LEADNew/unqualified lead
APPOINTMENT_BOOKEDAppointment scheduled
NO_SHOWLead did not attend appointment
RESCHEDULEDAppointment rescheduled
CANCELEDAppointment canceled
PARTIAL_PAYMENTPartial payment received
WONDeal won/closed
UNQUALIFIEDLead disqualified
FOLLOW_UPRequires follow-up
LOSTDeal lost

Touch Point Type Values

ValueDescription
PHONE_CALLPhone call
WHATSAPPWhatsApp message
EMAILEmail
FOLLOW_UP_CALLFollow-up phone call
PROPOSAL_REVIEWProposal review meeting
OTHEROther touchpoint type

Nested Objects Reference

User Object Fields

FieldTypeDescription
first_namestringFirst name
last_namestringLast name
emailstringEmail address
profile_image_urlstringProfile image URL (null if none)
idstringClerk user ID
rolestringOrganization role

Source Object Fields

FieldTypeDescription
idstringMarketing source ID
namestringMarketing source name

Status Object Fields

FieldTypeDescription
idstringStatus ID
namestringStatus display name
rolestringStatus role (enum value)
descriptionstringStatus description
text_colorstringHex color code for text
bg_colorstringHex color code for background

Touch Point Object Fields

FieldTypeDescription
idstring (UUID)Touchpoint ID
ownerobject | nullTeam member who owns the touchpoint. See User Object. Null if the user can no longer be resolved.
owner_idstringClerk user ID of the owner
typestring (enum)Touchpoint type. See Touch Point Type Values.
due_atstring (ISO 8601)UTC timestamp the touchpoint is due.
has_timebooleanWhether an explicit time was chosen. When false, only the date of due_at is meaningful.
notestring | nullShort touchpoint note
created_atstring (ISO 8601)UTC timestamp of creation.

Billing Details Object Fields

FieldTypeDescription
idstringBilling details ID
business_namestringCompany/business name
addressstringStreet address
citystringCity
zipcodestringPostal/ZIP code
provincestringState/province
countrystringISO 3166-1 alpha-2 country code
vat_numberstringVAT/tax ID number
vat_exemptbooleanWhether the lead is marked VAT-exempt
created_atstring (ISO 8601)When billing details were added
updated_atstring (ISO 8601)When billing details were last updated

Note Object Fields

FieldTypeDescription
notestringNote content
mention_usersarrayUsers @mentioned in the note (always empty on list)

Counts Object Fields

FieldTypeDescription
notesintegerNumber of notes
appointmentsintegerNumber of appointments
contractsintegerNumber of contracts
paymentsintegerNumber of payments
opt_insintegerNumber of opt-in submissions
deliveriesintegerNumber of delivery engagements

Custom Field Object Fields

FieldTypeDescription
idstringCustom field definition ID
namestringCustom field name
valueanyField value (type depends on field definition)

Error Responses

400Validation error (e.g. missing or empty note, note over 10,000 characters, or an assignment user ID that is not an active member of the workspace)
json
{
  "status": "error",
  "message": "note is required"
}
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": "Rate limit exceeded for this organization. Retry after the number of seconds in the Retry-After header."
}