Write, debug, and tune Playwright specs with locator strategy, trace diagnosis, and CI-aware timeouts.
Coding
CRM Snail Mail (PostGrid)
Try itSend physical mail from CRM contacts using PostGrid. Use when pulling contacts from GoHighLevel (GHL) or Follow Up Boss (FUB), mapping contact/address fields...
What it does
Use this skill to run targeted direct-mail outreach from CRM contacts.
The skill document
CRM Snail Mail via PostGrid
Use this skill to run targeted direct-mail outreach from CRM contacts.
Workflow
- Pick source:
ghl,fub, or pre-exported contact JSON. - Pull and normalize contacts into a common schema.
- Filter to records with mailable addresses.
- Build personalized message content.
- Submit jobs to PostGrid (
lettersorpostcards) with dry-run available. - Return send summary with success/failure per contact.
Script
scripts/crm_postgrid_mailer.pyPurpose: Pull contacts from GHL/FUB (or load from JSON), normalize fields, render templates, and send to PostGrid.scripts/postgrid_api.pyPurpose: Full PostGrid API utility with broad endpoint catalog andcall-rawfallback for any documented endpoint.
Environment Variables
GHL_API_KEY: GHL API key/token.GHL_BASE_URL(optional): defaults tohttps://services.leadconnectorhq.com.FUB_API_KEY: Follow Up Boss API key.FUB_BASE_URL(optional): defaults tohttps://api.followupboss.com/v1.POSTGRID_API_KEY: PostGrid API key.POSTGRID_BASE_URL(optional): defaults tohttps://api.postgrid.com/print-mail/v1.
Typical Commands
List full PostGrid endpoint catalog included in this skill:
python3 scripts/postgrid_api.py list-endpoints
Call a cataloged PostGrid endpoint:
python3 scripts/postgrid_api.py call contacts.list
Call any PostGrid endpoint directly (full docs coverage fallback):
python3 scripts/postgrid_api.py call-raw GET /letters \
--base-url https://api.postgrid.com/print-mail/v1
Normalize contacts from FUB to JSON:
python3 scripts/crm_postgrid_mailer.py fetch \
--provider fub \
--limit 200 \
--output /tmp/fub_contacts_normalized.json
Normalize contacts from GHL to JSON:
python3 scripts/crm_postgrid_mailer.py fetch \
--provider ghl \
--location-id "$GHL_LOCATION_ID" \
--limit 200 \
--output /tmp/ghl_contacts_normalized.json
Dry-run PostGrid payload generation:
python3 scripts/crm_postgrid_mailer.py send \
--contacts-file /tmp/ghl_contacts_normalized.json \
--from-json-file references/example_sender_us.json \
--html-template-file references/example_letter_template.html \
--mail-route letters \
--dry-run
Fetch + send in one command:
python3 scripts/crm_postgrid_mailer.py run \
--provider fub \
--limit 100 \
--from-json-file references/example_sender_us.json \
--html-template-file references/example_letter_template.html \
--mail-route letters \
--output /tmp/mail_send_summary.json
Send one ad-hoc mailer from raw address + content:
python3 scripts/crm_postgrid_mailer.py one-off \
--to-name "Jane Seller" \
--to-address1 "742 Evergreen Terrace" \
--to-city "Springfield" \
--to-state "IL" \
--to-postal-code "62704" \
--from-json-file references/example_sender_us.json \
--content-text "Hi Jane,\n\nI'd love to send you a fresh home valuation this week.\n\nBest,\nDaniel" \
--mail-route letters \
--dry-run
Use JSON exported by another GHL/FUB skill:
python3 scripts/crm_postgrid_mailer.py run \
--contacts-file /tmp/contacts_from_other_skill.json \
--from-json-file references/example_sender_us.json \
--html-template-file references/example_letter_template.html \
--mail-route letters
Data Contract
Normalized contact shape:
idfirst_namelast_namefull_nameemailphoneaddress1address2citystatepostal_codecountrytagsraw
Contacts missing address1, city, state, or postal_code are skipped by default.
Integration Notes
- If dedicated GHL/FUB skills exist and already return contact JSON, pass that file with
--contacts-fileand skip API pulling. - If APIs change, adjust mapping candidates in
scripts/crm_postgrid_mailer.pyinstead of rewriting workflow. - Use
--postgrid-routewhen account-specific PostGrid routes differ from defaults.
PostGrid Safety
- Start with
--dry-runto inspect generated payloads. - Keep
--max-sendduring first live run (for example--max-send 10). - Include clear campaign metadata using
--description.
See references/postgrid-notes.md for route/header assumptions and override strategy.
Related skills
More from danielfoch
Browse all skillsManage realtor tasks in GoHighLevel CRM including contact search and updates, pipeline tracking, messaging, calendar slots, and workflow enrollment via API v2.
Book real estate showing tours from emailed or pasted listing details, including extracting listing data, preparing outbound call jobs, coordinating a callin...
Command-line tool to manage contacts, tasks, notes, deals, events, and communications via the Follow Up Boss API.
Generate comparative market analysis (CMA) and home valuation reports from IDX listing data and selected comparable properties. Use when a user wants to pick...
Send Slybroadcast ringless voicemail campaigns from OpenClaw/LLMs using CLI or MCP, including AI voice generation (ElevenLabs or generic HTTP voice API) and...
Manage Pipedrive CRM from OpenClaw using API v1, including people, organizations, deals, leads, activities, notes, pipelines, and custom endpoint actions. Us...