Monitor New Florida DBA Registrations for Your Brand
A fictitious-name (DBA) filing is how someone registers a trade name to do business under. Polling the Sunbiz Daily API for names that match your brand lets you spot look-alikes within days of registration — a practical, low-cost input to brand and trademark monitoring. Look-alikes also appear as new corporations, LLCs, and partnerships, so a thorough watch covers all three record types.
Search fictitious names
On /api/v2/fictitious-names/, the fictitious_name filter is a
case-insensitive substring match. Pair it with a period for a rolling window of
newly registered trade names. Every mirror name column is trigram-indexed, so this search is
fast — the same speed as the corporate name search below.
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/fictitious-names/?fictitious_name=sunshine&period=30d"Check corporate names and partnerships too
Brand collisions also register as corporations and LLCs (corporation_name on
/api/v2/filings/) and as partnerships (name on
/api/v2/partnerships/). All three name filters behave the same way — substring,
case-insensitive, and trigram-indexed — so cover all three for a complete watch.
# Corporations and LLCs
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/filings/?corporation_name=sunshine&period=30d"
# Partnerships (LP / LLP / GP)
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/partnerships/?name=sunshine&period=30d"Each name filter accepts comma-separated values, ORed together, so you can watch several brand variants in one call (see Narrow your terms below).
Get the registrant with include=parties
When a look-alike turns up, the next question is who filed it. Add
include=parties and each row gains its owners (or officers /
partners) inline — so a single list request returns both the matching businesses and
the people behind them, with no per-row detail call.
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/fictitious-names/?fictitious_name=sunshine&period=30d&include=parties"
{
"filings": [
{
"fictitious_name": "SUNSHINE STATE PROPERTY PARTNERS",
"document_number": "G26000083540",
"status": "A", "county": "ORANGE",
"city": "ORLANDO", "state": "FL", "zip": "32801",
"owners": [
{ "position": 1, "name": "BEGINNERS PROPERTY ACADEMY LLC" }
]
}
],
"pagination": { "total": 1, "page": 1, "per_page": 25, "total_pages": 1, "total_capped": false }
}
Without include=parties the owners field is null, keeping
the default payload small. Owners are redaction-masked: a registrant who filed a privacy takedown
returns no parties (the business name and city still appear, so you never miss the match itself).
The reliability gotcha: poll wide, never narrow
This is the one thing that decides whether a brand watch actually catches everything. The API exposes only the filing date — there is no "ingested at" timestamp you can query. Sunbiz releases filings to us with a lag, so the most recent filing-dates are always still filling in: a match dated today may not land in the mirror until a day or two later.
That breaks the obvious design — "every run, fetch the last 7 days." Filings dated inside last week's window keep arriving after this week's window has already slid past them, so a narrow, non-overlapping poll misses them permanently. There is no ingestion-time filter to catch up with later.
The fix is to make the window much wider than your polling interval and dedupe on your side:
- Poll a wide, overlapping window. Run daily or weekly, but always re-scan a
full
period=30d. Late-arriving filings fall inside the next run's window and get picked up.periodonly accepts7d,14d, and30d— any other value silently falls back to 7 days, so for a window wider than 30 days use an explicitstart_date(e.g.start_date=2026-01-01) instead. - Deduplicate persistently. Keep a durable set of
document_number(fictitious / partnership) andcorporation_number(corporate) values you have already alerted on, so the overlap doesn't re-alert. - Treat "new since last run" as "in my window but not in my seen-set" — never as "filed since my last run." The two are not the same here.
This recipe watches for newly registered look-alikes. To instead check whether a name is
already registered (regardless of when), drop the date window entirely — use
period=all, or a start_date far enough back to cover it — since an
existing registration may be months or years old.
Narrow your terms
Substring matching casts a wide net, so a short or generic term pulls in unrelated businesses:
fictitious_name=sun returns SUNNY STYLES and
SUNCOAST SENIOR INSURANCE ADVISORS alongside any real "Sun" brand. Watch distinctive,
specific terms — and list the variants you care about with comma-OR rather than one loose stem:
# Watch several distinct brand variants in one call
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/fictitious-names/?fictitious_name=tesla,starlink&period=30d"
Two optional filters tighten the watch further. status=active drops dissolved or
withdrawn registrations (an unknown status value returns 422, never a silent no-op),
and county=MIAMI-DADE scopes to a single county if your brand is regional:
curl -H "X-API-Key: sb_your_key_here" \
"https://sunbizdaily.com/api/v2/fictitious-names/?fictitious_name=sunshine&status=active&county=MIAMI-DADE&period=30d"
One more thing to know about counts: a very broad term reports a capped total. When more than
10,000 rows match, the response returns "total": 10000 with
"total_capped": true — so don't read total as an exact match count for a
loose stem. Specific brand terms stay far under the cap, where total is exact.
Build the watch
Putting it together: scan all three resources over a wide overlapping window, request owners inline, and dedupe persistently so only genuinely new look-alikes alert.
from datetime import date, timedelta
import requests
API_KEY = "sb_your_key_here"
HEADERS = {"X-API-Key": API_KEY}
BASE = "https://sunbizdaily.com/api/v2"
DAYS = 30 # look-back window; set wider than your polling interval
# Persist this between runs (file, DB, Redis, etc.) — it is what makes a
# wide, overlapping window safe to re-scan without re-alerting.
SEEN = set()
# (endpoint, name filter, dedupe key) for each record type.
RESOURCES = [
("fictitious-names", "fictitious_name", "document_number"),
("filings", "corporation_name", "corporation_number"),
("partnerships", "name", "document_number"),
]
# Distinct brand variants, ORed. Keep them specific — substring is greedy.
TERMS = "sunshine widgets,sunshinewidgets"
def new_matches(endpoint, name_field, key_field):
# Use start_date for the window, not period=Nd: `period` only accepts
# 7d / 14d / 30d and silently falls back to 7 days for anything else, so
# start_date is the only way to widen past 30 days. A wide window absorbs
# late-ingested filings.
params = {
name_field: TERMS,
"start_date": (date.today() - timedelta(days=DAYS)).isoformat(),
"include": "parties", # owners/officers/partners inline, no detail call
"status": "active",
"per_page": 100,
}
url = f"{BASE}/{endpoint}/"
page = 1
while True:
params["page"] = page
resp = requests.get(url, headers=HEADERS, params=params, timeout=30)
resp.raise_for_status()
body = resp.json()
for row in body["filings"]:
key = row[key_field]
if key not in SEEN:
SEEN.add(key)
yield endpoint, row
pg = body["pagination"]
if page >= pg["total_pages"]:
break
page += 1
for endpoint, name_field, key_field in RESOURCES:
for kind, hit in new_matches(endpoint, name_field, key_field):
name = hit.get("fictitious_name") or hit.get("corporation_name") or hit.get("name")
owners = hit.get("owners") or hit.get("officers") or hit.get("partners") or []
who = ", ".join(o["name"] for o in owners) or "(redacted)"
print(f"New {kind}: {name} filed by {who}")- Schedule the script daily or weekly and route new matches to email or a chat webhook. The wide window means the interval only changes how fast you hear, not whether you catch a filing.
- Stay under the 1,000-requests-per-hour limit — a handful of brand terms across three resources is well within it.
Prefer a no-code version?
The Lead Mining workspace runs this kind of watch for you: save a brand search and get daily email alerts when new matching filings land — no script, no dedupe bookkeeping. The API is the right tool when you need the matches inside your own systems; Lead Mining is the right tool when you just want the alerts.
Next steps
Create a free key on your API Keys dashboard, then see the API documentation for the full fictitious-name, corporate, and partnership field lists.
Informational purposes only; provided without warranty. Searches run over a delayed third-party mirror with broad substring matching, so results may miss filings or include unrelated ones. Sunbiz Daily is not affiliated with the Florida Division of Corporations and accepts no liability for matches missed, false positives, or actions taken on its output. Always verify against the official Sunbiz.org records before acting, and consult an attorney for trademark matters. Not legal advice.