Send SMS and make voice calls via Dialpad API using task-focused wrappers backed by an OpenAPI-generated CLI.
Resources
7Install
npx skillscat add kesslerio/dialpad-openclaw-skill Install via the SkillsCat registry.
SKILL.md
Dialpad Skill
Send SMS and make voice calls via the Dialpad API.
When to Use
Use this skill to:
- Send SMS messages (individual or batch)
- Make voice calls (with TTS or custom voices)
- Manage contacts and organization settings
- Inspect SMS history through operator tooling when needed
Available Phone Numbers
| Number | Purpose | Format |
|---|---|---|
| (415) 520-1316 | Sales Team | Default for sales context |
| (415) 360-2954 | Work/Personal | Default for work context |
| (415) 991-7155 | Support SMS Only | SMS only (no voice) |
Quick Start
Send SMS (explicit sender recommended):
bin/send_sms.py --to "+14155551234" --from "+14155201316" --message 'Hello from OpenClaw!'Create/approve an SMS draft (human approval path):
bin/create_sms_draft.py --thread-key "manual:thread" --to "+14155551234" --from "+14155201316" --message 'Exact draft text' --json
bin/approve_sms_draft.py smsdraft_abc123 --actor-id "telegram-user-123" --actor-username "operator" --approval-token "$DIALPAD_SMS_APPROVAL_TOKEN" --jsonGroup Intro (mirrored fallback):
bin/send_group_intro.py --prospect "+14155550111" --reference "+14155559999" --confirm-share --from "+14153602954"Make Call (TTS):
bin/make_call.py --to "+14155551234" --text "This is a call from the agent."List Recent Calls:
bin/list_calls.py --today --limit 20
bin/list_calls.py --hours 6 --missed --jsonGet Call Transcript:
bin/get_call_transcript.py --call-id "call_123" --json
bin/get_call_transcript.py --last --with "+14155551234" --jsonCheck SMS Thread History:
bin/list_sms_thread.py --phone "+14155551234" --jsonSync Direct Dialpad SMS Sends:
bin/sync_sms_export.py --start-date 2026-05-13 --end-date 2026-05-13 --jsonCreate Contact:
bin/create_contact.py --first-name "Jane" --last-name "Doe" --phone "+14155550123" --email "jane@example.com"Update Contact:
bin/update_contact.py --id "contact_123" --phone "+14155550123" --job-title "VP"Key Rules
- Format: Always use E.164 format for numbers (e.g.,
+14155551234). - Escaping: Use single quotes for inline
--messagevalues containing$to prevent shell expansion (e.g.,'Price is $10'). - Safer message input: Prefer
--message-fileor--message-stdinfor pricing text, multi-line copy, or anything shell-sensitive. - Supported agent interface: use
bin/*.pywrappers for normal work. They are the stable command contract for agents. - Operator-only surfaces:
generated/dialpadandscripts/*are for manual troubleshooting, storage inspection, or operational maintenance, not normal agent task execution. - Auth canonical source:
DIALPAD_API_KEYis canonical.DIALPAD_TOKENis only needed for manual generated CLI troubleshooting.- Operator example:
export DIALPAD_TOKEN="${DIALPAD_TOKEN:-$DIALPAD_API_KEY}"
- Operator example:
- SMS sender safety:
--fromand--profile work|salesare supported. Prefer explicit--fromfor deterministic routing.--profilemaps to configured env vars:- work:
DIALPAD_PROFILE_WORK_FROM - sales:
DIALPAD_PROFILE_SALES_FROM
- work:
- default fallback order:
DIALPAD_DEFAULT_FROM_NUMBER, thenDIALPAD_DEFAULT_PROFILE --allow-profile-mismatchpermits explicit/profile mismatches when intentional--dry-runprints sender resolution and the exact message/request preview without an API call
- Group intro:
bin/send_group_intro.pymirrors intro messages as two one-to-one SMS sends (mirrored_fallback) because true group threads are unsupported via this wrapper. - Call history:
bin/list_calls.pyis the supported call-history command for agents. Use--jsonwhen downstream automation needs a deterministic response envelope. - Call transcripts:
bin/get_call_transcript.pyis the supported transcript retrieval command for agents. It uses Dialpad's plural transcript endpoints (GET /api/v2/transcripts/{call_id}and optional review URLGET /api/v2/transcripts/{call_id}/url); singular/api/v2/transcript/{id}is not the supported endpoint. It is transcript-only; AI recap, CRM enrichment, and follow-up drafting are intentionally separate work. - SMS thread history: Before saying a contact was not already messaged, run
bin/list_sms_thread.py --phone PHONE --jsonand checkhas_outbound/outbound_count. This local SQLite history is the supported current-turn response-state check. SetDIALPAD_SMS_DBwhen the runtime SMS database lives outside the default/home/art/clawd/logs/sms.dbpath; AlphaClaw uses/home/art/niemand/logs/sms.db. - SMS export sync:
bin/sync_sms_export.pyimports Dialpad Stats text export metadata into local SQLite for direct Dialpad UI sends and other out-of-band messages. It skips existing message IDs to preserve webhook-captured text. - Create/Update Contact Behavior:
bin/create_contact.pyupserts shared/local contacts by phone/email match (or forces create with--allow-duplicate).bin/update_contact.pyupdates by--idwith partial fields. - Current-turn verification: "Already sent" and "Already updated" are only valid after a fresh current-turn tool result, not from stale session memory. If the current turn has not verified the action yet, say that plainly and run the tool now.
- Identity guardrail: For first-contact work, soft signals like first name, area code, industry, or job title are not enough to merge or update a contact. Keep uncertain identity
draft-onlyand let the CRM layer prove the match before mutating anything. - Inbound context guardrail: Webhook
inboundContextbriefs explain identity evidence, recent SMS/call continuity, source status, and draft basis. Low-confidence Sales SMS and missed calls may get generic approval drafts, but not personalized claims. Known contacts only get context-aware, CRM-aware, or meeting-aware approval drafts when identity confidence is high and relevant continuity is no older than 14 days; stale or degraded context stays brief-only. Calendar lookup is only for obvious meeting logistics, not every inbound SMS. Demo-context missed calls may include operator-only prior-comms provenance from SMS/Gmail counts; raw comms bodies must not be copied into customer-facing draft text. If a model is used for final wording, it must receive compact tool-call facts plus the deterministic fallback and fail closed to that fallback on unsafe or unsupported output. - Inbound automation guardrail: Dialpad inbound hooks may create SMS approval drafts, but they must not send customer SMS directly. Use
bin/approve_sms_draft.pyonly with a real human actor id and an operator-onlyDIALPAD_SMS_APPROVAL_TOKEN; agent/bot actors are rejected by the approval ledger. - Opt-out guardrail: Explicit opt-out language is a hard stop. Do not create override drafts or send follow-ups on those threads unless a human operator handles the conversation outside automation.
Reference Documentation
references/api-reference.md— Wrapper behavior, operator CLI reference, Webhooksreferences/openclaw-integration.md— End-to-end setup guide for wiring this repo's webhook server to OpenClaw with human approval defaultsreferences/sms-storage.md— SQLite commands, FTS5 search, legacy storagereferences/voice-options.md— List of available TTS voices (Budget & Premium)references/architecture.md— System architecture, wrappers, and CLI generation
Operational Tools
Use these only for manual operator workflows, storage inspection, and maintenance:
python3 scripts/sms_sqlite.py list
python3 scripts/webhook_server.pySetup
Required environment variable:
export DIALPAD_API_KEY="your_key"Operator auth bridge for manual generated CLI troubleshooting:
export DIALPAD_TOKEN="${DIALPAD_TOKEN:-$DIALPAD_API_KEY}"Optional:
export ELEVENLABS_API_KEY="your_key"
export DIALPAD_USER_MAP='{"+14153602954": "5765607478525952"}'
export DIALPAD_PROFILE_WORK_FROM="+14153602954"
export DIALPAD_PROFILE_SALES_FROM="+14155201316"
export DIALPAD_DEFAULT_PROFILE="work"
export DIALPAD_DEFAULT_FROM_NUMBER="+14155201316"