Martindale APImartindale.com ↗
Search attorneys and law firms on Martindale-Hubbell. Get profiles, contact details, practice areas, ratings, and reviews via 6 structured endpoints.
What is the Martindale API?
The Martindale-Hubbell API gives programmatic access to one of the oldest attorney directories in the US through 6 endpoints covering attorney search, full profiles, law firm listings, and peer reviews. The search_attorneys endpoint returns paginated results with name, firm, phone, location, and rating for any keyword-and-location query, while get_attorney_profile surfaces structured schema.org LegalService data alongside biography sections and practice areas.
curl -X GET 'https://api.parse.bot/scraper/eed6d376-ffc6-44cf-8dcc-230a69cfdfdb/search_attorneys?query=personal+injury&location=New+York%2C+NY' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace martindale-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Martindale-Hubbell SDK — search attorneys, drill into profiles and reviews."""
from parse_apis.martindale_hubbell_api import Martindale, SearchType, AttorneyNotFound
client = Martindale()
# Search for personal injury attorneys in New York
for attorney in client.attorneysummaries.search(query="personal injury", location="New York, NY", limit=3):
print(attorney.name, attorney.firm_name, attorney.phone)
# Drill into the first result's full profile
summary = client.attorneysummaries.search(query="criminal defense", location="Chicago, IL", limit=1).first()
if summary:
profile = summary.details()
print(profile.name, profile.address, profile.practice_areas)
# Walk the attorney's peer endorsement reviews
for review in profile.reviews.list(limit=3):
print(review.meta, review.text[:80])
# Fetch a law firm and list its attorneys
firm = client.lawfirms.get(profile_url="https://www.martindale.com/organization/sweet-james-accident-attorneys-2937264/newport-beach-california-4811996-f/")
print(firm.name, firm.about[:60] if firm.about else "")
for member in firm.attorneys.list(limit=5):
print(member.name, member.title)
# Typed error handling for a missing profile
try:
client.attorneys.get(profile_url="https://www.martindale.com/attorney/nonexistent-0000000/")
except AttorneyNotFound as exc:
print(f"Not found: {exc.profile_url}")
# Retrieve search filters using the SearchType enum
filters = client.filtersets.get(query="family law", location="Los Angeles, CA", search_type=SearchType.ATTORNEYS)
print(filters.filters)
print("exercised: attorneysummaries.search / details / reviews.list / lawfirms.get / attorneys.list / attorneys.get / filtersets.get")
Full-text search over the Martindale-Hubbell attorney directory. Returns paginated attorney cards with name, firm, phone, location, and peer-review rating. Results are ordered by best match by default. Each card carries a profile_url suitable for get_attorney_profile and a firm_url suitable for get_law_firm_profile.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number for pagination. |
| queryrequired | string | Search keyword matching practice area or attorney name (e.g. 'personal injury', 'criminal defense'). |
| locationrequired | string | Location as city and state or ZIP code (e.g. 'New York, NY', 'Los Angeles, CA'). |
{
"type": "object",
"fields": {
"page": "integer, the current page number",
"attorneys": "array of attorney objects with name, profile_url, firm_name, firm_url, phone, location, and rating"
},
"sample": {
"data": {
"page": 1,
"attorneys": [
{
"name": "John Doe",
"phone": "+1 (555) 012-3456",
"rating": "Peer Reviews",
"firm_url": "https://www.martindale.com/organization/sweet-james-accident-attorneys-2937264/newport-beach-california-4811996-f/?pa=282",
"location": "Newport Beach, CA Personal Injury Attorney",
"firm_name": "Sweet James Accident Attorneys",
"profile_url": "https://www.martindale.com/attorney/john-doe-4853037/?pa=282"
}
]
},
"status": "success"
}
}About the Martindale API
Attorney Search and Profiles
The search_attorneys endpoint accepts a query string (e.g. 'personal injury', 'criminal defense') and a location string (city/state or ZIP) and returns a paginated list of attorney objects. Each object includes name, profile_url, firm_name, firm_url, phone, location, and rating. The page parameter controls pagination. The profile_url values from search results feed directly into get_attorney_profile, which returns the attorney's full name, a numeric atty_id extracted from the URL, a sections object mapping section titles like 'Biography' and 'Peer Reviews' to their text content, and a schema object containing schema.org LegalService structured data including address, telephone, practice areas, and ratings.
Law Firm Data
The get_law_firm_profile endpoint takes a profile_url (from search_attorneys results via firm_url) and returns the firm's name, an about description string (or null if absent), and a people array listing associated attorneys with their name, profile_url, and title. For larger firms, get_law_firm_attorneys provides the same attorney list with pagination support via the page parameter, making it suitable for enumerating all attorneys at firms with extensive rosters.
Reviews and Search Filters
The get_attorney_reviews endpoint retrieves endorsement reviews by atty_id — the numeric ID found in any attorney profile URL. Results are paginated and include a reviews array of objects with a meta field containing reviewer information and a text field containing the review content, plus a content_type label. The get_search_filters endpoint accepts a query, location, and search_type ('attorneys' or 'law-firms') and returns a filters object containing grouped filter options — including practice areas, peer review status, languages, law schools, and other facets — useful for building dynamic filter UI or scoping narrower searches.
The Martindale API is a managed, monitored endpoint for martindale.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when martindale.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official martindale.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a legal referral tool that queries
search_attorneysby practice area and ZIP code to surface local attorneys with ratings. - Aggregate attorney profile data including
sections(bio, peer reviews) and schema.org fields to populate a legal professional database. - Monitor law firm rosters using
get_law_firm_attorneysto detect staff changes over time. - Collect peer endorsement reviews via
get_attorney_reviewsfor reputation analysis or attorney vetting workflows. - Enumerate available practice area and language filters with
get_search_filtersto build a guided attorney-search interface. - Enrich a CRM with attorney contact data by piping
phone,location, andfirm_namefromsearch_attorneysinto lead records. - Cross-reference attorney credentials and bar affiliations using profile
sectionsand schema.org structured data fields.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Martindale-Hubbell have an official developer API?+
What does `get_attorney_profile` return beyond basic contact info?+
sections object that maps named sections — such as 'Biography' and 'Peer Reviews' — to their text content, a schema object with schema.org LegalService structured data (address, telephone, practice areas, ratings), the attorney's name, and a numeric atty_id extracted from the profile URL. The atty_id is what you pass to get_attorney_reviews to fetch endorsements.Does the API return client ratings or only peer review ratings?+
get_attorney_reviews endpoint returns endorsement-style reviews with a content_type field and reviewer metadata. The schema object in attorney profiles includes rating data as structured by schema.org. Granular breakdowns of client ratings versus peer ratings as separate numeric scores are not currently exposed as distinct fields. You can fork the API on Parse and revise it to add a dedicated endpoint targeting those data points.How does pagination work across endpoints?+
search_attorneys, get_law_firm_attorneys, and get_attorney_reviews all accept an integer page parameter and return the current page number in the response. There is no total_pages or total_results field returned, so you determine the end of results when an empty array is returned.Can I retrieve a list of all attorneys in a state without a specific keyword?+
search_attorneys endpoint requires both a query and a location input — neither is optional. Broad location-only browsing without a practice area or name keyword is not currently supported. You can fork the API on Parse and revise it to add an endpoint that relaxes the query requirement for broader geographic sweeps.