Reference · Payloads
Lead bundles
Where bundles come from
| Channel | Use it to | How |
|---|---|---|
| Webhook | Receive each lead as it is qualified | lead.qualified deliveries |
| REST | Fetch one property's bundle | GET /leads/{id} |
| MCP | Fetch one bundle | greenfinch_get_lead_bundle |
| MCP | Export a saved list page by page | greenfinch_get_lead_bundles |
Every channel builds the same bundle, applies the same field settings, and is billed the same way. Bundles leave one property at a time; there is no bulk dump.
Example
{
"bundle_version": 1,
"greenfinch_property_id": "3f2a9c1e-0000-4000-8000-000000000001",
"generated_at": "2026-09-14T15:04:05.000Z",
"delivered_to_org": "org_example000000000001",
"partial": false,
"partial_reason": null,
"property": {
"address": "1200 Commerce Pkwy",
"city": "Plano",
"state": "TX",
"zip": "75074",
"county": "Collin",
"lat": 33.0198,
"lon": -96.6989,
"common_name": "Northgate Business Park",
"common_name_confidence": 0.92,
"lot_sqft": 217800,
"building_sqft": 96000,
"building_sqft_is_planned": false,
"year_built": 2004,
"year_built_detail": {
"basis": "per_building",
"oldest": 1998,
"newest": 2004,
"primary_building_basis": "area",
"buildings": 3,
"buildings_total": 3
},
"num_floors": 4,
"num_floors_detail": {
"basis": "per_building",
"max": 4,
"area_weighted_mean": 3.51,
"primary_building": 4,
"primary_building_basis": "area",
"buildings": 3,
"buildings_total": 3
},
"effective_year_built": 2015,
"effective_year_built_detail": {
"basis": "per_building",
"oldest": 2009,
"newest": 2015,
"primary_building_basis": "area",
"buildings": 2,
"buildings_total": 3
},
"heating_type": "Rooftop Package Unit",
"heating_type_detail": {
"basis": "per_building",
"buildings": 3,
"buildings_total": 3,
"area_share": 1,
"values": [
{
"value": "Rooftop Package Unit",
"buildings": 2,
"area_share": 0.844
},
{
"value": "Heat Pump",
"buildings": 1,
"area_share": 0.156
}
]
},
"cooling_type": "Rooftop Package Unit",
"cooling_type_detail": {
"basis": "per_building",
"buildings": 3,
"buildings_total": 3,
"area_share": 1,
"values": [
{
"value": "Rooftop Package Unit",
"buildings": 2,
"area_share": 0.844
},
{
"value": "Heat Pump",
"buildings": 1,
"area_share": 0.156
}
]
},
"primary_construction_type": "Concrete",
"primary_construction_type_detail": {
"basis": "per_building",
"buildings": 3,
"buildings_total": 3,
"area_share": 1,
"values": [
{
"value": "Concrete",
"buildings": 3,
"area_share": 1
}
]
},
"exterior_wall_material": null,
"exterior_wall_material_detail": null,
"foundation_type": "Slab on Grade",
"foundation_type_detail": {
"basis": "per_building",
"buildings": 3,
"buildings_total": 3,
"area_share": 1,
"values": [
{
"value": "Slab on Grade",
"buildings": 3,
"area_share": 1
}
]
},
"roof_cover": null,
"roof_cover_detail": null,
"roof_shape": null,
"roof_shape_detail": null,
"quality_grade": "Good",
"quality_grade_detail": {
"basis": "per_building",
"buildings": 3,
"buildings_total": 3,
"area_share": 1,
"values": [
{
"value": "Good",
"buildings": 2,
"area_share": 0.844
},
{
"value": "Average",
"buildings": 1,
"area_share": 0.156
}
]
},
"has_pool": false,
"has_pool_detail": {
"basis": "per_building",
"count": 0,
"buildings": 3,
"buildings_total": 3
},
"has_sprinklers": true,
"has_sprinklers_detail": {
"basis": "per_building",
"count": 2,
"buildings": 2,
"buildings_total": 3
},
"building_attributes_basis": "per_building",
"footprint_area": 21500,
"footprint_area_source": "measured",
"asset_category": "Office",
"asset_subcategory": "Office Building",
"category_confidence": 0.95,
"beneficial_owner": "Northgate Holdings Group",
"beneficial_owner_type": "private_investor",
"beneficial_owner_confidence": 0.8,
"ownership_type": "private",
"management_company": "Lakeside Property Services",
"registered_owner": "Northgate Business Park LLC",
"assessed_total_val": 18450000,
"last_sale_date": "2017-05-22",
"last_sale_price": 16900000,
"last_transfer_date": null,
"revenue_estimates": {
"landscaping": {
"mid": 42000,
"low": 31000,
"high": 55000,
"tier": 2
}
},
"property_website": "https://northgate.example.com",
"ai_rationale": "Four-story multi-tenant office building on a landscaped campus…",
"property_phone": "(972) 555-0118",
"property_phone_confidence": 0.7,
"last_enriched_at": "2026-08-20T14:11:00.000Z",
"deep_link_url": "https://app.greenfinch.ai/property/3f2a9c1e-0000-4000-8000-000000000001"
},
"organizations": [
{
"greenfinch_organization_id": "3f2a9c1e-0000-4000-8000-000000000021",
"role": "property_manager",
"attribution_type": "named_for_property",
"is_current": true,
"name": "Lakeside Property Services",
"domain": "lakeside.example.com",
"location": {
"city": "Dallas",
"state": "TX",
"postal_code": "75201"
},
"industry": "Real Estate",
"employees": 140,
"employees_range": "51-200",
"linkedin_handle": "lakeside-property-services-example",
"phone_numbers": [
"(214) 555-0100"
]
}
],
"contacts": [
{
"greenfinch_contact_id": "3f2a9c1e-0000-4000-8000-000000000011",
"role": "property_manager",
"attribution_type": "named_for_property",
"relationship_status": "active",
"relationship_confidence": "high",
"stale_pending_review": false,
"identity_not_confirmed": false,
"full_name": "Dana Whitfield",
"title": "Director of Facilities",
"email": "dana.whitfield@example.com",
"email_validation_status": "valid",
"linkedin_url": "https://www.linkedin.com/in/example-dana-whitfield",
"employer_name": "Lakeside Property Services",
"phones": [
{
"value": "(214) 555-0142",
"label": "direct_work",
"type": "Direct",
"fallback_from_employer": false
}
],
"phone_e164": "+12145550142",
"confidences": {
"name": 0.95,
"email": 0.9,
"linkedin": 0.85
}
}
],
"contacts_summary": null,
"pipeline": {
"in_pipeline": true,
"status": "qualified",
"deal_value": 48000,
"status_changed_at": "2026-09-12T16:40:11.000Z",
"lost_reason": null,
"disqualified_reason": null,
"assigned_rep": {
"greenfinch_user_id": "3f2a9c1e-0000-4000-8000-000000000031",
"name": "Jordan Example",
"email": "jordan.rep@example.com"
}
},
"notes": [
{
"id": "3f2a9c1e-0000-4000-8000-000000000041",
"author_name": "Jordan Example",
"created_at": "2026-09-11T14:00:00.000Z",
"content": "Spoke with facilities; landscaping contract renews in Q1."
}
],
"notes_digest": "2026-09-11 — Jordan Example: Spoke with facilities; landscaping contract renews in Q1.",
"actions": [
{
"id": "3f2a9c1e-0000-4000-8000-000000000051",
"action_type": "call",
"description": "Follow up before renewal",
"due_at": "2026-10-01T15:00:00.000Z",
"status": "pending",
"completed_at": null,
"assignee_name": "Jordan Example",
"created_by_name": "Jordan Example",
"created_at": "2026-09-11T14:02:00.000Z"
}
],
"actions_digest": "2026-10-01 — Call (pending): Follow up before renewal"
}Fields
Every field is always present; a value Greenfinch does not have is null (or an empty array). Your organization admin can switch off groups of contact and organization fields for all exports on the Integrations page; switched-off fields arrive as null (phone lists as empty arrays). IDs, roles and relationship flags are never switched off.
Removed on 2026-09-16: property.calculated_building_class, property.building_class_rationale, property.management_type and organizations[].estimated_annual_revenue. Nothing ever populated these keys, so no data was lost.
Changed 2026-09-16: where a county lists every building on a site, year_built carries the year of the building with the most floor area — or, when that building's record gives no year, of the largest building that does — and num_floors carries the tallest building's floor count, rounded up to a whole floor.
Envelope
| Name | Type | Description |
|---|---|---|
bundle_versionrequired | 1 | Schema version. Fields can be added, and a field that never carried a value can be removed, without changing it. A populated field is never removed within a version. |
greenfinch_property_idrequired | uuid | The property's stable ID — the key to de-duplicate on. |
generated_atrequired | ISO-8601 | When the bundle was assembled. |
delivered_to_orgrequired | string | Your organization's ID. |
partialrequired | boolean | true only for a webhook delivery of a property that was not unlocked; see contacts_summary. |
partial_reasonrequired | "not_revealed" | null | Why the bundle is partial. |
property
| Name | Type | Description |
|---|---|---|
address, city, state, zip, countyrequired | string | Validated location. address is always set. |
lat, lonrequired | number | Parcel centre. |
common_namerequired | string | The property's name. A common_name_confidence of 0.4 or less means an address-style fallback, not a known name. |
lot_sqft, building_sqftrequired | number | Lot and building floor area. building_sqft_is_planned marks planned rather than built floor area. |
year_built, effective_year_built, num_floorsrequired | number | When the building was built, when it dates from once renovations are counted, and its floor count. On a site with several buildings: the year of the building with the most floor area (or, when that building's record gives no year, of the largest building that does), and the tallest building's floor count. |
heating_type, cooling_type, primary_construction_type, exterior_wall_material, foundation_type, roof_cover, roof_shaperequired | string | Building details from a fixed list of values. On a site with several buildings, the value covering the most floor area. Wall material, roof cover and roof shape are empty on most properties today. |
quality_graderequired | string | The construction-quality grade the county assessor recorded to value the building for tax, on that county's own scale. A rough tier, not an inspection and not a statement about the building's condition today. |
has_pool, has_sprinklersrequired | boolean | true when at least one building has one; false only when the county says there is none; null when it does not say. Sprinklers are empty on most properties today. |
<field>_detailrequired | object | Beside each building detail above (not the footprint below): how many buildings it covers (buildings, buildings_total), its share of floor area, every value on the site for a list-valued detail (values, whose first entry is always the value itself), the oldest and newest year, or the tallest floor count as the county records it (num_floors is that figure rounded up) and the average. Present whenever the value is, unless a stored per-building breakdown could not be read, in which case the value still ships and the detail is null. basis is per_building when every building was combined and main_building_only when only one main-building record is known, in which case the counts are null. |
building_attributes_basisrequired | "per_building" | "main_building_only" | null | How the building details were put together; null only when the property has none of them. |
footprint_area, footprint_area_sourcerequired | number / string | The building's footprint in square feet as the Greenfinch property page shows it, and whether it is measured or an estimate (county_record is reserved for a county's recorded foundation area and does not occur yet). Empty on plans without premium property data. No detail object. |
asset_category, asset_subcategoryrequired | string | What the property is, with category_confidence. |
beneficial_owner, beneficial_owner_typerequired | string | Who really owns it, with beneficial_owner_confidence and ownership_type. |
management_companyrequired | string | Who manages it. |
registered_ownerrequired | string | The owner of record on the county's assessor roll. |
assessed_total_val, last_sale_date, last_sale_price, last_transfer_daterequired | number / date | Assessed value; the county's last recorded sale and its price; a later recorded transfer. |
revenue_estimatesrequired | object | Estimated annual service revenue by service category: mid, low, high and a size tier. |
property_website, property_phonerequired | string | Discovered contact points, with property_phone_confidence. |
ai_rationalerequired | string | The research write-up. |
last_enriched_atrequired | ISO-8601 | When the property was last researched. |
deep_link_urlrequired | string | The property's page in the Greenfinch app. |
organizations[]
| Name | Type | Description |
|---|---|---|
greenfinch_organization_idrequired | uuid | The firm's stable ID. |
rolerequired | string | The firm's relationship to the property: owner, property_manager, operator (runs a site it does not own and decides its upkeep) or tenant (occupies space without deciding upkeep; recorded, never the buyer). |
attribution_typerequired | string | The strength of the evidence, strongest first: named_for_property, portfolio_evidence, roster_deterministic, roster_llm, coverage_inferred, county_record. |
is_currentrequired | boolean | Whether the relationship is current. |
name, domain, locationrequired | string / object | Firm identity and city, state and postal code. |
industry, employees, employees_rangerequired | string / number | Firmographics. |
linkedin_handle, phone_numbersrequired | string / string[] | The firm's LinkedIn handle and main office numbers. |
contacts[]
| Name | Type | Description |
|---|---|---|
greenfinch_contact_idrequired | uuid | The contact's stable ID. |
role, attribution_typerequired | string | Decision-maker role at this property and the evidence behind it. |
relationship_statusrequired | string | active, job_change_detected, former, needs_review, demotion_withheld or retraction_withheld. |
relationship_confidencerequired | string | high, medium or low. |
stale_pending_reviewrequired | boolean | true when the relationship is under review; do not treat the contact as confirmed-current. |
identity_not_confirmedrequired | boolean | true when the person's current job could not be confirmed; the title and employer are unconfirmed. |
full_name, title, employer_namerequired | string | Who the person is. |
email, email_validation_statusrequired | string | Email and "valid" or "unknown". Unknown means found but not yet confirmed deliverable — not invalid. |
linkedin_urlrequired | string | Profile URL. |
phones[]required | object[] | Deliverable numbers: value, label (the stored label), type ("Mobile", "Direct", "Office" or null) and fallback_from_employer (true when the number is the employer's main line, not the person's). |
phone_e164required | string | The primary number in E.164 form for matching; null when the only number is an employer fallback. |
confidencesrequired | object | Confidence in name, email and linkedin, 0–1. |
contacts_summary
null on a full bundle. On a partial bundle it replaces contacts: total_count and, per contact, title and availability (email, phone, linkedin booleans) — what unlocking would give you, without names or values.
pipeline, notes and actions
| Name | Type | Description |
|---|---|---|
pipeline.in_pipelinerequired | boolean | false when the property has no pipeline record (the status is then a default of new). |
pipeline.status, deal_value, status_changed_atrequired | string / number | The current stage, deal value and when it changed. |
pipeline.lost_reason, disqualified_reasonrequired | string | Why a deal was lost or disqualified. |
pipeline.assigned_reprequired | object | greenfinch_user_id, name and email of the owner, or null. |
notes[]required | object[] | id, author_name, created_at and content. notes_digest is the same history as plain text. |
actions[]required | object[] | Every task — pending, completed and cancelled — with action_type, description, due_at, status, completed_at, assignee_name, created_by_name and created_at. actions_digest is the same history as text. |
How deliveries are metered
On Team plans, bundle deliveries are metered per delivery:
- A free monthly allowance. Each billing period your organization can export a set number of bundles free. The allowance and how much is used are in GET /account (
egress_quota). - Then 1 credit each. Once the allowance is used, every delivered bundle costs 1 credit, on every channel.
- Every delivery counts. Fetching the same property twice is two deliveries.
On Enterprise plans, bundle deliveries draw the records allowance your order states, at no credit cost, on every channel — a bundle counts its property plus each distinct firm and person inside it, once per record per billing period. A bundle with two firms and two people in it is five records; fetching that same property again in the same period adds nothing.
- Unlocking is separate. A bundle includes contacts only for properties your organization has unlocked (10 credits, once) or that your subscription covers.
- Daily limits. An admin can cap deliveries per day for the organization and per key; see daily limits.
Each REST response tells you how it was billed in meta.billed_via (quota or credit) and meta.credits_charged.
Availability — 15 September 2026
The move of Enterprise deliveries from the per-delivery meter to the records allowance is rolling out from mid-September 2026, with each Enterprise order. Until it reaches your organization, Enterprise deliveries are metered exactly like Team's — the free monthly allowance, then one credit each — and the dry-run and ceiling controls below apply unchanged. Team plans do not change.
Dry runs and spend ceilings
greenfinch_get_lead_bundles exports a saved property list one page at a time and is built so a job never spends more than you approved.
1. Price the page with a dry run
curl -X POST "https://app.greenfinch.ai/api/v1/mcp" \
-H "Authorization: Bearer $GREENFINCH_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "greenfinch_get_lead_bundles",
"arguments": {
"listId": "3f2a9c1e-0000-4000-8000-000000000071",
"limit": 25,
"offset": 0,
"dryRun": true
}
}
}'{
"dryRun": true,
"listName": "Plano office prospects",
"list_members": 42,
"hidden_from_you": 0,
"page_size": 25,
"offset": 0,
"projected_deliveries": 22,
"projected_refusals": 3,
"projected_outcomes": [
{
"property_id": "3f2a9c1e-0000-4000-8000-000000000001",
"outcome": "would_deliver"
},
{
"property_id": "3f2a9c1e-0000-4000-8000-000000000013",
"outcome": "would_refuse",
"refusal_code": "NOT_ENTITLED"
}
],
"projected_via_quota": 18,
"projected_credits": 4,
"note": "Nothing was delivered or charged. 3 of 25 properties on this page would be refused and cost nothing — see projected_outcomes."
}A dry run delivers and charges nothing. projected_credits counts only the properties this page can actually deliver — a property that will be refused (not unlocked, outside your territory) is never charged for, and is listed in projected_outcomes with its refusal_code. The figure is bounded by today's remaining daily export allowance as well, since deliveries past it do not happen, and then by your free monthly allowance, which is spent before any credit is. If a page is long enough that the allowance runs out part-way, the properties beyond that point are not examined at all and are reported as not_projected rather than counted either way.
2. Run it with a ceiling
curl -X POST "https://app.greenfinch.ai/api/v1/mcp" \
-H "Authorization: Bearer $GREENFINCH_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "greenfinch_get_lead_bundles",
"arguments": {
"listId": "3f2a9c1e-0000-4000-8000-000000000071",
"limit": 25,
"offset": 0,
"maxCredits": 7
}
}
}'maxCreditsis the most the call may spend beyond the free allowance. Leaving it out means0: only free exports happen.- If the page would cost more than
maxCredits, the call refuses withCOST_CONFIRMATION_REQUIREDand the projected numbers, before delivering anything. Call again with a higher ceiling to confirm. - The ceiling is re-checked before every delivery. If credits, the allowance or a daily limit run out mid-page, the call stops early, keeps what it delivered, and says so in
stopped_earlyandnote. - Each result lists an
outcomesentry per property (delivered,refusedwith arefusal_code, orfailed), thebundles, andcredits_charged. - Continue with
next_offsetuntil it comes backnull. It always points at the first property the call did not finish with, so nothing is skipped. - A run that stopped early returns
next_offset: null— continuing unchanged would stop in the same place — plusstopped_earlysaying what ran out andresume_offset, the property to start from once it has been dealt with (the daily cap resets, or you raisemaxCredits).
Single-bundle calls (GET /leads/{id}, greenfinch_get_lead_bundle) have no ceiling argument: each costs at most 1 credit. Check egress_quota first if you need to stay within the allowance.