Enrichment Functions
Ten edge functions handle attorney and firm enrichment. The primary pipeline uses the Blitz API v2 for LinkedIn-based enrichment (email, phone, work history). Additional functions handle firm website URL detection and scraping.
Blitz API Functions
blitz-enrich-attorney-contacts
The primary enrichment function. Enriches email and phone for a batch of attorneys using the Blitz API v2.
Input
interface EnrichRequest {
attorneyIds: string[]; // UUIDs of attorneys to enrich
skipPhone?: boolean; // Skip phone enrichment (saves 5 credits/attorney)
skipEmail?: boolean; // Skip email enrichment
}
Flow
Blitz API v2 Endpoints
| Endpoint | Method | Cost | Input Field |
|---|---|---|---|
/v2/enrichment/email | POST | 1 credit if found | person_linkedin_url |
/v2/enrichment/phone | POST | 5 credits if found | person_linkedin_url |
The Blitz API v2 uses person_linkedin_url (NOT linkedin_profile_url). Using the wrong field name results in a 422 error.
Email Response Handling
interface BlitzEmailResponse {
email: string | null;
email_status: 'valid' | 'invalid' | 'catch_all' | 'unknown';
work_email: string | null;
all_emails: string[];
}
Only valid, invalid, catch_all, unknown are accepted. The value "unverified" does NOT exist and will cause an insert error.
Credit Costs
| Operation | Cost |
|---|---|
| Email enrichment | 1 credit if found, 0 if not |
| Phone enrichment | 5 credits if found, 0 if not |
| Typical per attorney | 2-7 credits |
blitz-update-sparse-attorneys
Updates attorney records that have incomplete data. Targets attorneys where key fields (email, phone, education) are missing.
Input
interface UpdateRequest {
firmId?: string; // Scope to a specific firm
limit?: number; // Max attorneys to process
}
Logic
- Query attorneys where
email_primary IS NULLorphone_mobile IS NULL - For each, call Blitz email and/or phone enrichment
- Update the record with new data
enrich-firm-attorneys
Bulk enrichment for all attorneys at a specific firm. Combines employee finding + email + phone enrichment.
Input
interface FirmEnrichRequest {
firmId: string;
maxAttorneys?: number; // Default 100
skipPhone?: boolean;
}
Flow
- Load firm's LinkedIn URL from
firmstable - Call
/v2/search/employee-finderwith the firm's LinkedIn URL - Filter results to valid attorney titles
- Enrich each with email and phone
- Upsert to
attorneystable
URL Detection & Scraping Functions
detect-firm-url-patterns
Tests multiple URL pattern templates against a firm's website to find their attorney bio page format.
Input
interface DetectRequest {
firmId: string;
}
Logic
- Load 2 enriched attorneys from the firm (need real names to test)
- Test 37 URL patterns (e.g.,
/people/{first}-{last},/lawyers/{last}) - Make HEAD requests to each generated URL
- If 200 OK, validate with a second attorney
- Save the working pattern to
firms.profile_url_pattern
Known Patterns
| Firm | Pattern |
|---|---|
| Most firms | /people/{first}-{last} |
| Kirkland & Ellis | /lawyers/{last_initial}/{last}-{first} |
| Gibson Dunn | /lawyers/{last} |
| Latham & Watkins | /people/{last} |
| Cleary Gottlieb | /professionals/{first}-{last} |
| WilmerHale | /bio/{first}-{last} |
search-attorney-profile-urls
Uses the detected firm URL pattern to generate profile URLs for all attorneys at a firm.
Input
interface SearchUrlsRequest {
firmId: string;
limit?: number;
}
Flow
- Load firm's
profile_url_patternandwebsite - Load attorneys for the firm
- Generate URL for each attorney using the pattern
- Validate each URL with a HEAD request
- Store valid URLs in
attorneys.firm_website_profile
find-attorney-urls
Alternative URL finder that uses search techniques rather than pattern matching. Useful for firms with non-standard URL patterns.
scrape-attorney-profiles
Web scraping function that extracts detailed attorney information from firm website bio pages. Populates the 34 website-scraping fields in the attorneys table.
Fields Extracted
- Practice areas (primary, secondary, specialties)
- Bar admissions (state and court)
- Rankings (Chambers, Legal 500, Best Lawyers)
- Awards and recognitions
- Publications count
- Office phone number
- Education details (honors, major)
- Representative matters
- Languages
Side Effects
- Updates up to 34 columns in
attorneys - Sets
website_scraped_attimestamp - Updates
enrichment_level
match-profile-urls-to-attorneys
Links scraped firm website profiles to existing attorney records. Uses name matching to connect URLs found on firm websites to the corresponding attorneys rows.
populate-firm-websites
Backfills firms.website and firms.domain for firms that are missing this data. Uses the firm's LinkedIn URL to find their website.
Market Population Functions
populate-market
Creates or updates a market definition and links qualifying attorneys.
Input
interface PopulateMarketRequest {
marketId: string;
criteria: {
practiceArea?: string;
geography?: string;
seniority?: string;
firmTier?: string;
};
}
populate-market-attorneys
Links attorneys to a market based on the market's criteria. Queries the attorneys table using the market's filters and creates market_attorneys records.
preview-firm-attorneys
Returns a preview of attorneys at a firm that would be included in a market, without actually creating records. Used for UI previews before populating.