Building a contact sync

Add MCP server to your AI tool

Allow AI tools and LLMs to interact with the API documentation portal through MCP.

MCP server URL

https://bump.sh/realscout/doc/realscout-api/mcp

Standard setup for AI tools providing an mcp.json file

mcp.json
{
  "RealScout API MCP server": {
    "url": "https://bump.sh/realscout/doc/realscout-api/mcp"
  }
}

Close

This guide covers keeping your CRM's contacts and your RealScout contacts in step: a first full import, then regular runs that pick up only what changed.

Before you start: check for a built-in integration

RealScout already syncs natively with Follow Up Boss, Cloze, kvCORE, MoxiWorks and Rechat. If you use one of those, turn on that integration from the Integrations page instead of building your own.

Don't run both against the same CRM. The two would be importing and updating the same contacts, so changes get applied twice or passed back and forth in a loop.

Using the API alongside a built-in integration

You can use the API and a built-in integration at the same time, as long as the API doesn't do the integration's job. Each contact has one owner, and that owner decides where the contact's details come from.

  • Contacts the integration brought in belong to your CRM. Each time your CRM sends an update, RealScout copies these fields from it, replacing what's in RealScout:
    • name, phones, street, city, state and zip
    • additional email, and lead source
    • email, for a contact who hasn't signed in yet

Changes you make to these fields through the API aren't sent to your CRM, and they're replaced on the next update. Make those changes in your CRM. Use the API for what your CRM doesn't send: favorite, agreements, alert preferences, your own tags, archive and Auto Nurture.

  • Contacts you create through the API belong to the API. RealScout never sends them to your CRM. The integration also never takes them over, even if the same person (same email) is added to your CRM later.

That second rule is deliberate. The API is how you bring contacts into RealScout from systems you run yourself. If RealScout passed those contacts on to your CRM, a sync that reads from your CRM and writes to RealScout would send every contact straight back where it came from, as a duplicate or in a loop. If the integration could take over a contact your tool created, your CRM's next update would quietly undo your tool's edits. With one owner per contact, neither can happen.

So if a person belongs in your CRM, add them in your CRM and let the integration bring them into RealScout. Create a contact through the API only when your CRM isn't involved.

Keep a map of ids

Every RealScout contact has an id. Store it next to your CRM's id for the same person, and match on that pair from then on.

Don't match on names. Email works for the first import (see below), but people change their email, and the pair of ids won't change.

You can also set external_user_key to your own id when you create a contact, and look a contact up with the external_user_key filter. Two limits: it can only be set at creation, so contacts created in RealScout never have one, and it isn't enforced unique. Treat it as a convenience, not your map.

The first run: pull everything

Page through GET /contacts with limit=100 until next_cursor is null. Store each contact's id, plus whatever fields you sync.

To match existing CRM records to these contacts, use email. A RealScout email is unique per agent, so GET /contacts?email=... returns at most one contact.

Later runs: only what changed

Use updated_after to fetch only the contacts changed since your last run:

  1. Note the time before you start, not after you finish.
  2. Page through GET /contacts?updated_after=<last run's start time>&limit=100.
  3. Apply each contact to your CRM, keyed by id.
  4. Save this run's start time for next time.

Using the start time means a contact changed while your run was going still gets picked up next time. Subtract a minute for clock drift. updated_after includes contacts changed at exactly that time, so you'll see a few contacts twice. That's harmless as long as applying a contact is safe to repeat.

What updates a contact's updated_at: edits to its fields, archiving and unarchiving, Auto Nurture changes, and tags added or removed by the agent or through the API. RealScout's automatic tags (realscout_tags) and tags synced from another CRM (external_tags) don't update it.

Writing back to RealScout

  • Creating: POST /contacts. If a contact already has that email, you get 400 invalid_request with field: "email". Look the contact up by email and store its id instead of retrying. If the contact at that email was deleted, creating brings them back.
  • Updating: PATCH /contacts/{id}. Fields you leave out stay as they are, and a field sent as null is cleared. Send only the fields your CRM owns, so you don't wipe out what the agent entered in RealScout.
  • Tags: POST /contacts/tags/add and /remove. Each takes up to 100 contact ids at a time, and both are safe to repeat.

Archived and deleted contacts

An archived contact stays in the list with status.value set to ARCHIVED. Use ?status=ARCHIVED to list only those. Archive and unarchive with POST /contacts/archive and /unarchive.

A contact the agent deletes disappears from the list, and updated_after never reports the deletion. To find deletions, run a full sweep now and then, for example nightly or weekly. Collect every id from GET /contacts and compare against your map. An id missing from the sweep has been deleted in RealScout.

Avoiding a write loop

If your sync writes to RealScout and reads changes back, each write you make shows up in your next updated_after run. Before writing a contact back to your CRM, compare it with what you last sent. Only write fields that actually changed, so the two systems settle instead of passing the same contact back and forth.

Staying inside the limits

A sync is mostly list calls: 60 a minute per token, 100 contacts per page. That's up to 6,000 contacts a minute. Make one token just for the sync, so it can't use up the budget your other tools need. When you get a 429, wait the number of seconds in Retry-After. See Limits, paging and errors.