CapScout
How it worksFeatures
For investorsSet the return you need. Underwrite what clears it.For agents & teamsFind what each investor client should buy next.For property managersFind each owner's next rental, then manage it.
PricingLearn
ContactLog inStart for free Start free
How it worksFeaturesSolutionsFor investorsFor agents & teamsFor property managersPricingLearnContactLog in
Developers

Connect CapScout to the tools you already run

API v1 · Team plans · times are ISO 8601 in UTC

CapScout's CRM has a small API and signed webhooks. Use them to bring leads in from anywhere, keep another CRM in step, or build on what happens in your book. People flow in from your other tools. Investor activity (reports sent and opened, stage moves, deals) flows out from CapScout.

Get a key

An Owner or Admin creates keys in Settings → Integrations. A key is shown once. It acts as the member who made it: it sees the contacts they see, and it stops working if they leave the team or stop being an Owner or Admin. Send it on every request:

Authorization: Bearer csk_live_…

The base URL is https://api.capscout.ai/v1/api. Requests and responses are JSON. A key gets 120 requests a minute.

Endpoints

GET/me

Who this key is: the team, the key and the member it acts as. Use it to test a connection.

POST/leads

Add a lead from anywhere. It is routed, given its first follow-ups and announced to its agent like any other lead.

GET/contacts

The contacts the key’s member can see, newest change first. Filter by email, phone, stage, search or updated_since.

POST/contacts

Create a contact, or update the one already under that email: 201 for new, 200 for existing. An update sets name and phone and adds tags. Notes, stage, owner and visibility are set on create only.

GET/contacts/{id}

One contact.

POST/contacts/{id}/touches

Log a call, text, email, meeting or note on the person’s timeline. Send external_id and the same one files once.

POST/contacts/{id}/stage

Move the person to a stage. The move is logged and the stage’s follow-ups start.

GET/events

What happened in the book, newest first. Filter by kind. With since_id you get the events after it, oldest first, and has_more says whether to ask again.

POST/hooks

Subscribe a URL to events (REST hooks). The answer carries the signing secret.

DELETE/hooks/{id}

Unsubscribe. Answering a delivery with 410 Gone does the same.

Add a lead

curl https://api.capscout.ai/v1/api/leads \
  -H "Authorization: Bearer csk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Habib Rahman",
    "email": "habib@example.com",
    "phone": "904-555-0142",
    "message": "Looking for duplexes under $400k",
    "source_name": "Facebook Lead Ads"
  }'

Send at least one of name, email or phone. source_name is what your team sees as the lead's source. If the email already belongs to a client, the lead goes to the agent who works them.

Request bodies

Every field is optional unless it says otherwise.

POST /leads

name, email, phoneAt least one of the three.
messageWhat they asked. Kept on the lead; events and webhooks don’t carry it.
source_nameThe source your team sees on the lead. Defaults to the key’s name.

POST /contacts

emailHow an existing contact is found. A new one needs a name or an email.
name, phoneSet on create, and on update.
tagsA list of up to 30. An update adds to the tags already there.
stagenew, contacted, active, under_contract, closed or owner. Create only; defaults to active.
notesCreate only.
owner_emailA member of the team. Create only; defaults to the key’s member.
visibilityprivate, team or org. Create only; defaults to private.

POST /contacts/{id}/touches

kindcall, text, email, meeting or note. Required. A note sends no event.
directionoutbound (the default) or inbound.
summaryOne line, up to 255 characters.
bodyThe notes. They stay in CapScout.
occurred_atISO 8601. Defaults to now.
external_idYour id for it. The same one twice files once.

POST /contacts/{id}/stage

stagenew, contacted, active, under_contract, closed or owner. Required.

POST /hooks

urlA public https:// address. Required.
kindsA list of event names from Events below. Leave it out for all of them, including any added later.

A contact linked to your team’s connected CRM (today, Zoho CRM) takes its name and phone from there, so an update here skips those two fields.

Lists

GET /contacts takes limit (up to 100) and offset, and answers { "results": [...], "next_offset": 50 }. next_offset is null on the last page.

Events

Ten things can happen. Subscribe a webhook to any of them, or poll GET /events?kind=….

lead.createdA lead came in from a report, your form, an email, a portal or the API.
contact.createdSomeone was added to the book. A CSV import stays silent.
contact.stage_changedA contact moved to a new stage.
touch.loggedA call, text, email or meeting was logged.
report.sentA report was shared with a client.
report.viewedA client opened a report. Sent on the first open, then at most daily.
client.hotA client keeps coming back to their reports.
deal.stage_changedA deal moved on the pipeline.
matches.foundNew homes fit a client's buy box.
client.verdictA client said yes, maybe or no to a home you sent.

Every event has the same envelope, by webhook or by poll:

{
  "id": "evt_1842",
  "type": "report.viewed",
  "created_at": "2026-09-17T14:02:11.482913Z",
  "organization": { "id": 102 },
  "contact": {
    "id": 311,
    "name": "Grace Liu",
    "email": "grace@example.com",
    "phone": "904-555-0188",
    "stage": "active",
    "tags": ["investor", "1031"],
    "owner_email": "ana@yourbrokerage.com",
    "url": "https://app.capscout.ai/clients/311"
  },
  "data": {
    "home": {
      "property_id": "18-Fairfield-Ave-Jacksonville-FL-32206",
      "mode": "rental",
      "address": "18 Fairfield Ave, Jacksonville, FL 32206",
      "url": "https://app.capscout.ai/property/…/details?mode=rental"
    },
    "views": 3
  }
}

An event carries ids, names and links, plus the contact’s email, phone, stage, tags and owner’s email. The text of an email and the notes under a touch never leave CapScout. Only the one-line summary an agent types on a logged touch travels.

Webhooks

Add a URL in Settings → Integrations, or subscribe one with POST /hooks. It has to be a public https:// address. Answer with any 2xx within 10 seconds. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, then dropped. A URL that accepts nothing for two days is paused and its Owners and Admins are told. Answer 410 Gone to unsubscribe.

Verify a delivery

Each delivery carries X-CapScout-Timestamp and X-CapScout-Signature. The signature is v1= plus the HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with the endpoint's signing secret. X-CapScout-Delivery is unique per delivery, so you can drop a repeat.

import crypto from "node:crypto";

// rawBody is the request body exactly as received, before any JSON parsing.
export function isFromCapScout(secret, headers, rawBody) {
  const timestamp = headers["x-capscout-timestamp"];
  const expected = "v1=" + crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");
  const given = headers["x-capscout-signature"] ?? "";
  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
  return fresh && given.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}
import hashlib, hmac, time

def is_from_capscout(secret: str, headers, raw_body: bytes) -> bool:
    timestamp = headers["X-CapScout-Timestamp"]
    signed = timestamp.encode() + b"." + raw_body
    expected = "v1=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    fresh = abs(time.time() - int(timestamp)) < 300
    return fresh and hmac.compare_digest(expected, headers.get("X-CapScout-Signature", ""))

Zapier, Make and n8n

CapScout on Zapier

The CapScout app on Zapier has a trigger for each of the ten events, the actions Create Lead, Create or Update Contact, Log Touch and Move Contact Stage, and a Find Contact search. You connect it with an API key. Find CapScout on Zapier.

Any tool, by webhook

No app and no code needed. In Zapier, add a Webhooks by Zapier → Catch Hook trigger, copy its URL, and add it as a webhook in CapScout. Pick the events you want and press Send a test so Zapier has a sample. For the other direction, use Webhooks by Zapier → POST with your key in the Authorization header to add a lead or log a touch. Make's Custom webhook and n8n's Webhook node work the same way.

Errors

Errors are JSON with a detail line written for a person. 401 means the key is missing, wrong or revoked. 403 means the team's plan has lapsed, or the key's member can see a contact but not change it. 404 means nothing with that id is visible to the key. 429 means slow down; the Retry-After header says for how long.

The API is additive: we add fields and endpoints, and we don't rename or remove them. Building something and need a field that isn't here? Write to info@capscout.ai.

CapScout

An AI acquisition platform for investors and the firms that help them buy rentals and flips on the open market.

Product
FeaturesPricing
Resources
LearnCalculatorsCompare toolsHelpFAQDevelopers
Company
AboutHow it worksFor agents & teamsFor property managersContact
Legal
PrivacyTermsDisclaimersAgent & team termsCopyright / DMCAAccessibility
Featured on
  • CapScout — Featured on Startup Fame
  • CapScout — Featured on Fazier
  • CapScout — Verified on Dang.ai
  • CapScout — Featured on ToolPilot
  • Featured on launched.toolsREVIEWED ✓
  • CapScout — Featured on LaunchKiwi
© 2026 CapScout. Analysis is informational, not financial or investment advice.Map plates drawn in the manner of the Sanborn fire-insurance surveys.