Skip to main content

Custom fields & formData

Leads, contacts and product/services all accept writes through a single formData object that mixes system fields and custom fields. Understanding how the two are told apart is the key to the whole write API.

The rule

Inside formData, the server looks at each key:

  • A key that is a valid 24-character ObjectId → a custom field, matched by its _id.
  • Anything else → a system field on the schema.
{
"formData": {
"stage": "Qualified",
"priority": "High",
"665f1a2b3c4d5e6f70819200": "Enterprise"
}
}

stage and priority are system fields; 665f1a... is a custom field id. There is no separate customFields block — one flat object handles both.

Discovering custom fields

curl "https://api.leadx.in/api/key/protected/custom-field?filters=%7B%22panel%22%3A%22lead%22%7D" \
-H "apikey: $KEY"

panel is one of lead, contact, productService. Each definition carries:

FieldNotes
_idThe key you use in formData.
nameDisplay label.
fieldTypetext, number, textarea, select, multi-select, file, checkbox, date, email, url, object, array
valueTypestring, number, boolean, date, member, file, array, object
optionsFor select / multi-select — the allowed { label, value } entries.
requiredWhether a write must supply it.
defaultValueApplied when omitted.
uniqueFieldIDStable slug, handy for mapping to your own system.
section, order, hidePresentation only.

:::tip Cache the definitions, not the ids Custom field _ids are stable, but building your mapping from uniqueFieldID or name at startup keeps your integration readable and survives a field being recreated. :::

Reading custom field values

Values come back on customFieldsMap, keyed by field id:

{
"_id": "665f...",
"stage": "Qualified",
"customFieldsMap": {
"665f1a2b3c4d5e6f70819200": {
"value": "Enterprise",
"label": "Enterprise",
"sortValue": "enterprise"
}
}
}

value is what you wrote. label resolves select options to their display text. sortValue is a normalized form the server uses for sorting — ignore it.

The legacy fields array is still present on documents for backward compatibility. Read customFieldsMap; fields is the older representation.

Filtering and sorting by custom field

Use the field id as the path, exactly as in formData:

?filters={"665f1a2b3c4d5e6f70819200":"Enterprise"}
?sortBy=665f1a2b3c4d5e6f70819200&sortOrder=asc

Appending instead of replacing

For array-valued custom fields, a bulk update can add rather than overwrite:

{ "ids": ["665f..."], "updateType": "append", "formData": { "665f1a...": ["Tag A"] } }

updateType defaults to replace.

Managing definitions

MethodEndpointNotes
GET/custom-fieldList. Filter by panel.
POST/custom-fieldCreate. name and fieldType required.
GET/custom-field/:idRead one.
PUT/custom-field/:idUpdate.
DELETE/custom-fieldDelete — { "ids": [...] }.
PUT/custom-field/modifyBulk-modify definitions.
PUT/custom-field/reorderReorder within a section.
PUT/custom-field/reset-systemReset system field configuration to defaults.

Sections (/custom-section) group fields for display and follow the same CRUD-plus-reorder shape.

System fields worth knowing

Lead

stage · status · priority · source · notes · enquiryAt · contact · productServices · team · teamMember · plus ad attribution (ad_id, adset_id, campaignName) and UTM fields (utmSource, utmMedium, utmCampaign, utmTerm, utmContent, utmUrl).

FieldAllowed values
stageNew · Contacted · Follow-up Required · Qualified · Interested · Proposal Sent · Negotiation · Won · Lost · On Hold · Closed
statusHot · Warm · Cold
priorityHigh · Medium · Low
sourceBulk Import · Offline · Facebook · Website · AI Generated · Instagram · Whatsapp · SMS · Gmail · Zoho · LinkedIn · Twitter · Threads

An unrecognised source is dropped rather than rejected.

Contact

name · email · jobTitle · address · country · state · city · postalCode · description · tags · contactcategories, plus nested groups:

  • contactNumber, work_phone_number, whatsapp_contact_number — each { countryCode, number }
  • companyData{ name, website, industry, otherIndustry, size, location }
  • social{ facebook, twitter, linkedin, instagram, youtube, tiktok, personalWebsite }
FieldAllowed values
companyData.sizeSelf-employed · 0-10 · 11-50 · 51-200 · 201-500 · 501-1000 · 1001-5000 · 5001-10000 · 10000+
companyData.industryInformation Technology (IT) · Healthcare · Financial Services · E-commerce · Manufacturing · Education · Real Estate · Logistics · Media & Entertainment · Telecommunications · Automotive · Marketing · Legal Services · NGO · Other

Nested paths can be written either nested or dotted — {"companyData": {"name": "Acme"}} and {"companyData.name": "Acme"} are equivalent.