Field catalog update (June 28, 2026): Any references in this article to Ace Score, Ace Tier, Ace Status, Ace Response Time, Ace Velocity Score, Ace Days Since Inbound, or Ace Preferred Channel describe retired FUB custom fields kept only for historical workflow context. Ace no longer creates, writes, or updates those fields. The current catalog has two active free fields: Ace Win Score and Ace Churn Risk, plus five Ace Trove fields: Ace Expected GCI, Ace Opportunity, Ace Seller Tier, Ace Buyer Tier, and Ace Last Analyzed.

Parsing JSON Responses in the Follow Up Boss API

By the Follow Up Ace team· Last updated
Quick answer

Follow Up Boss returns collection data in a named array plus _metadata. Follow the server-provided next cursor until it is absent, validate the envelope on every page, and request fields=allFields when you need custom-field values.

Developer parsing JSON API response from Follow Up Boss CRM in code editor

How the Follow Up Boss REST API returns data

Follow Up Boss exposes a REST API at https://api.followupboss.com/v1/. Every response body is JSON. The content type is always application/json. There is no XML option, no GraphQL endpoint, and no streaming format — just straightforward request/response JSON over HTTPS.

The response shape depends on whether you are fetching a collection or a single resource:

Authentication before you can parse anything

The API uses HTTP Basic Authentication. Your API key is the username; the password field is left blank. Every request must include an Authorization header or the server returns 401 before you even see a JSON body.

# Example: Base64-encode API_KEY: (note the trailing colon, no password)
# Then set the Authorization header on every request:
Authorization: Basic <base64(API_KEY:)>
Content-Type: application/json

Most HTTP libraries handle the base64 encoding automatically when you supply a username and empty password. Never embed the raw API key in client-side code or commit it to source control — store it in an environment variable.

JSON response structure for contacts and leads

The /v1/people endpoint is the primary resource for contacts and leads. A collection response looks like this (illustrative example — field names and shape match FUB's public documentation):

{
  "people": [
    {
      "id": 12345,
      "firstName": "Jordan",
      "lastName": "Rivera",
      "stage": "New Lead",
      "source": "Website",
      "created": "2026-06-01T09:22:00Z",
      "updated": "2026-06-20T14:05:00Z",
      "emails": [
        { "value": "[email protected]", "type": "home" }
      ],
      "phones": [
        { "value": "5551234567", "type": "mobile" }
      ],
      "customAceWinScore": 74,
      "customAceChurnRisk": "High",
      "customAceOpportunity": "Active Buyer",
      "customAceBuyerTier": "High"
    }
  ],
  "_metadata": {
    "total": 842,
    "limit": 25,
    "offset": 0
  }
}

Key fields to know when parsing contact objects:

Field Type Notes
id integer Stable unique identifier; use this for updates and lookups
firstName / lastName string May be null if the contact was created from a phone number only
emails / phones array of objects Each item has value and type; a contact may have multiple entries
stage string Pipeline stage label; values depend on your FUB configuration
source string Lead origin; drives action plan assignment in FUB
created / updated ISO 8601 string UTC timestamps; parse with your language's date library
custom* varies Custom fields appear as top-level properties with their configured name

Handling pagination in Follow Up Boss API responses

All list endpoints are paginated. The _metadata object in every collection response tells you how many total records exist and where your current page falls. Use limit and offset query parameters to walk through pages.

JavaScript pagination example

// Illustrative example — walks all contacts page by page
async function fetchAllPeople(apiKey) {
  const BASE = 'https://api.followupboss.com/v1/people';
  const auth = Buffer.from(`${apiKey}:`).toString('base64');
  const headers = { Authorization: `Basic ${auth}` };

  const limit = 100;
  let offset = 0;
  let total = Infinity;
  const results = [];

  while (offset < total) {
    const url = `${BASE}?limit=${limit}&offset=${offset}`;
    const res = await fetch(url, { headers });
    if (!res.ok) throw new Error(`FUB API error: ${res.status}`);

    const data = await res.json();
    total = data._metadata.total;
    results.push(...data.people);
    offset += limit;
  }

  return results;
}

Python pagination example

# Illustrative example using the requests library
import requests, os

def fetch_all_people(api_key):
    session = requests.Session()
    session.auth = (api_key, '')   # HTTP Basic Auth — password blank
    url = 'https://api.followupboss.com/v1/people'

    limit = 100
    offset = 0
    results = []

    while True:
        resp = session.get(url, params={'limit': limit, 'offset': offset})
        resp.raise_for_status()
        data = resp.json()

        results.extend(data['people'])
        total = data['_metadata']['total']
        offset += limit
        if offset >= total:
            break

    return results

A few practical notes on pagination:

Webhook JSON payloads from Follow Up Boss

Webhooks deliver event data to your endpoint as an HTTP POST with a JSON body the moment something changes in FUB — a contact is created, a stage transitions, a note is added. This is the right pattern for any integration that needs to react in near real-time rather than polling.

A personCreated webhook payload looks similar to the single-resource contact GET response, wrapped in an event envelope:

{
  "event": "personCreated",
  "eventId": "evt_abc123",
  "uri": "https://api.followupboss.com/v1/people/12345",
  "data": {
    "id": 12345,
    "firstName": "Jordan",
    "lastName": "Rivera",
    "stage": "New Lead",
    "source": "Zillow",
    "created": "2026-06-26T10:00:00Z"
  }
}

Steps for reliable webhook processing:

  1. Register the webhook via POST /v1/webhooks with your url, event type, and optionally a secret for signature verification.
  2. Respond with 200 immediately. FUB expects a response within a few seconds. If you do not respond in time, FUB will retry delivery. Accept the payload, enqueue it to a background job, and return 200 before doing any processing.
  3. Verify the signature if you configured a secret — compare the HMAC digest in the request header against your own computation of the payload body.
  4. Parse data the same way you parse a single-resource contact response — same field names, same types.
  5. Handle duplicates using eventId. Webhook delivery is at-least-once; occasional duplicates are normal. Store processed event IDs and skip duplicates.

Parsing custom fields in the API response

Custom fields in Follow Up Boss are extensible properties you define in your account. When you retrieve a contact via the API, custom field values appear as top-level properties on the contact object, using the field's configured name as the key.

For example, if you have a custom field named customBuyerTimeline, its value appears directly on the contact JSON at the root level:

{
  "id": 12345,
  "firstName": "Jordan",
  "customBuyerTimeline": "3-6 months",
  "customBudgetRange": "600000-800000"
}

To write a custom field value, include it by name in your POST or PUT body. To discover what custom fields exist in an account, call GET /v1/customFields — this returns the field definitions including name, type, and available choices for dropdown fields.

Current Ace fields in the FUB API response

Follow Up Ace writes supported model outputs back to FUB as custom fields. The two free fields are customAceWinScore and customAceChurnRisk; Ace Trove adds five more fields.

Field name in API Type Description
customAceWinScore number (0–100) Within-account percentile rank of calibrated win probability, not a close probability
customAceChurnRisk string (dropdown) Low, Medium, or High risk that an engaged contact goes cold
customAceExpectedGCI number Calibrated win probability × the account's median commission (estimate; Trove)
customAceOpportunity string (dropdown) At Risk, Active Buyer, Active Seller, Likely Seller, or Nurture (Trove)
customAceSellerTier / customAceBuyerTier string (dropdown) Very High, High, Moderate, Low, or None relative propensity (Trove)
customAceLastAnalyzed date Date of the most recent completed Trove analysis

Paid Ace Trove accounts receive customAceExpectedGCI, customAceOpportunity, customAceSellerTier, customAceBuyerTier, and customAceLastAnalyzed. Live prose and evidence stay in Companion and the dashboards rather than stale text fields.

Reading them in JavaScript is no different from reading any other field:

// After fetching a contact object from GET /v1/people/{id}:
const contact = await fetchContact(id);

const aceWinScore = contact.customAceWinScore;   // number, e.g. 74
const churnRisk   = contact.customAceChurnRisk;  // string, e.g. "High"
const buyerTier   = contact.customAceBuyerTier;  // string, e.g. "High" (Trove)

// Null-safe access if the field may not be set yet:
const risk = contact.customAceChurnRisk ?? 'Unknown';

Using an AI connector instead of raw JSON parsing

If the goal is natural-language access to contact data rather than a deterministic data pipeline, parsing raw JSON yourself is the wrong level of abstraction. Follow Up Ace exposes a Model Context Protocol (MCP) connector at https://followupace.com/mcp that allows an AI assistant like Claude to search contacts, read scores, log notes, and trigger actions through conversation — no JSON parsing required on your end.

The Agentic connector sits on top of the same FUB API endpoints described in this article; it just handles authentication, pagination, and field mapping for you. For teams that want both layers — a reliable ETL pipeline for data sync and a conversational interface for ad-hoc queries — the two approaches complement each other well.

Common parsing pitfalls and how to avoid them

Further reading

Try Follow Up Ace in your Follow Up Boss

Free to start, no sales call. Connect Follow Up Boss in one click and Ace works inside your CRM.

Get Started Free