Real estate wholesaling automation
Screen wholesaling leads with AI agents and the Atlas API
By Atlas Proptech ·
An AI agent can use the Atlas Property Distress API to screen property leads, add visible condition data to a CRM, and prepare a review queue for a real estate wholesaler. Your team sets the rules and decides which leads to pursue.
1. What the Atlas API adds to a wholesaling workflow
The Atlas Property Distress API analyzes exterior street imagery. Send an address or coordinates and receive a distress score from 0 to 100, visible signals, an explanation, and image date and quality details. One synchronous request analyzes one property and returns the result.
An AI agent is software that can call tools and act on their results. You connect Atlas as one tool in your agent’s workflow. The agent can combine its result with lead data you already have in your CRM and prepare the next task.
2. The agent-powered workflow
- A new lead enters your CRM from a form, imported list, or referral.
- The agent reads the address and sends it to Atlas.
- On success, the agent saves the score, signals, explanation, and imagery details with the lead.
- If Atlas cannot analyze the property (
422), the agent marks the lead for manual review. Address not found, no panorama, panorama too old, and no visible building all use zero credits. - For analyzed leads, the agent applies your screening rules, updates the CRM, and creates a review task.
- A person reviews the lead before outreach or an offer.
The table shows how an agent can map each Atlas result to a CRM action:
| Atlas result | Agent action in the CRM |
|---|---|
| Score 70 or more, a structural signal, and imagery newer than 12 months | Set the lead status to “Priority review”. Create a review task. Attach the score, signals, and reasoning as a note. |
| Successful analysis that does not meet your thresholds | Save the result with the lead. Keep the lead in the normal follow-up queue. Create no task. |
| High score, but imagery older than 12 months | Save the result and tag the lead “Stale imagery”. Request a current photo or a drive-by before review. |
422: address not found, no panorama, panorama too old, or no visible building | Tag the lead “Manual screen”. Create a manual-review task. Zero credits are used. |
Keep an unavailable result separate from a low score. For temporary errors, use the retry guidance below.
3. How an agent can prioritize leads
Example rule: analysis.score >= 70, a structural signal in
analysis.signals, and imagery.date newer than 12 months.
These examples check selected roof, foundation, and wall signals.
Pass the parsed JSON from a successful API response to shouldPrioritize(result)
in TypeScript or should_prioritize(result) in Python:
TypeScript
// Fields used by this rule from a successful API response.
type ScreeningResult = {
status: "analyzed";
test?: boolean;
analysis: { score: number; signals: string[] };
imagery: { date: string | null };
};
function shouldPrioritize(
result: ScreeningResult, now = new Date()
): boolean {
const { analysis, imagery } = result;
const currentMonth = now.toISOString().slice(0, 7);
const cutoff = new Date(Date.UTC(
now.getUTCFullYear() - 1, now.getUTCMonth(), 1
)).toISOString().slice(0, 7);
const captureMonth = imagery.date ?? "";
const recent = /^\d{4}-(0[1-9]|1[0-2])$/.test(captureMonth)
&& captureMonth > cutoff && captureMonth <= currentMonth;
const structural = analysis.signals.some(signal =>
/sagging roof|foundation|damage to the walls/i.test(signal)
);
return result.status === "analyzed"
&& result.test !== true
&& analysis.score >= 70 && structural && recent;
} Python
import re
from datetime import datetime, timezone
def should_prioritize(
result: dict, now: datetime | None = None
) -> bool:
# result is the parsed JSON from a successful API response.
analysis, imagery = result["analysis"], result["imagery"]
now = (now or datetime.now(timezone.utc)).astimezone(timezone.utc)
current_month = now.strftime("%Y-%m")
cutoff = f"{now.year - 1:04d}-{now.month:02d}"
capture_month = imagery["date"] or ""
recent = bool(re.fullmatch(
r"[0-9]{4}-(0[1-9]|1[0-2])", capture_month
)) and cutoff < capture_month <= current_month
structural = any(
re.search(r"sagging roof|foundation|damage to the walls", signal, re.I)
for signal in analysis["signals"]
)
return (
result["status"] == "analyzed"
and result.get("test") is not True
and analysis["score"] >= 70 and structural and recent
)
Atlas dates use YYYY-MM. The rule compares capture months and excludes
missing dates, future months, and test responses. Adjust the threshold and signal list
to your market. Review image quality and distance with the evidence.
A match gives the lead priority for review; other leads can stay in the normal queue.
4. A minimal Atlas API example
This command uses Atlas’s free test address: 123 Test St, Atlantis, ZZ 00000.
Send it from your server or agent tool, with your key in an environment variable:
curl https://api.atlasproptech.com/v1/property-distress/analyze \
-H "x-api-key: $ATLAS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"property":{"address":"123 Test St, Atlantis, ZZ 00000"}}'
The live API returned this response to the test request. Atlas generates random test
values, so your response will differ. No imagery is fetched, no model runs,
and credits_used is 0:
{
"id": "3bccac1b-48a6-4c12-9a88-74481fd0e922",
"status": "analyzed",
"test": true,
"location": {
"coordinates": {
"lat": 0,
"lng": 0
},
"address": "123 Test St, Atlantis, ZZ 00000"
},
"analysis": {
"score": 37.6,
"signals": [
"overgrown yard",
"peeling or flaking paint"
],
"reasoning": "Test request. This response is randomly generated; no imagery was fetched and no model was involved."
},
"imagery": {
"date": "2026-09",
"distance_m": 28.1,
"quality_score": 85.4
},
"credits_used": 0,
"api_version": "2026-08-20"
} Use the API response reference for field definitions and the error reference for failure handling.
5. Where the workflow needs human review
Atlas provides a visual screening signal. It does not confirm ownership, seller motivation, repair cost, or property value. It is not an appraisal or inspection. While area search jobs check the latest transfer, the API currently does not perform this check. It returns the imagery date for your workflow to review. Send uncertain cases to a human reviewer and verify current conditions before a deal decision.
6. How to start
- Choose an active Base or Boss subscription. Explore, the pay-as-you-go plan with no monthly fee, does not include API access.
- Create a key at app.atlasproptech.com/developers. Each key is shown only once. Store it on your server.
- Connect your agent tool and test with
123 Test St, Atlantis, ZZ 00000. It returns a full synthetic response withtest: trueandcredits_used: 0. Subscription checks and rate limits still apply. - Try a small real lead set, compare the review queue with your team’s judgment, then expand from there!
To stay within rate limits, pace your calls at 5 req/s per key. Retry 429, 503, and 504
with increasing delays; honor the Retry-After header when present.
Error responses use zero credits. Each successful real analysis uses one shared Atlas credit.
7. Frequently asked questions
Can an AI agent call the Atlas API?
Yes. Connect an agent tool to POST /v1/property-distress/analyze and send the API key in x-api-key. Your integration runs the request and handles the CRM actions. Atlas requires an active subscription.
What data does the Atlas API return?
The Atlas Property Distress API returns analysis.score (0–100), analysis.signals, analysis.reasoning, imagery.date, imagery.distance_m, imagery.quality_score, and credits_used, plus the property location, response ID, status, and API version.
Does every API request use a credit?
No. Each successful real analysis uses one shared Atlas credit. All error responses use zero credits, including no imagery and panorama too old. The free test address also uses zero credits.
Can Atlas replace a property inspection?
No. Atlas screens visible exterior conditions in available street imagery. A person must check the property and other deal information before making a purchase decision.