# Sendly SMS API for developers. Send transactional and marketing SMS to 190+ countries. For AI agents and automation, use the tools below. ## MCP Server (85 tools) Add Sendly to Claude Code, Cursor, Codex, Windsurf, OpenClaw, GitHub Copilot, and any MCP client. Hosted (no install): `https://mcp.sendly.live` — Streamable HTTP, runs on Cloudflare's edge, no Node.js required. Local: `npx @sendly/mcp` — stdio transport, requires Node.js 18+ and SENDLY_API_KEY env var. - [Hosted MCP Server](https://mcp.sendly.live) — 85 tools, Bearer token auth - [MCP Discovery](https://sendly.live/.well-known/mcp.json) - [npm: @sendly/mcp](https://www.npmjs.com/package/@sendly/mcp) - [MCP Architecture](https://sendly.live/docs/concepts/mcp-architecture) — security model, design decisions - [MCP Setup Guide](https://sendly.live/docs/ai/mcp-setup) — per-platform setup instructions - [MCP Tools Reference](https://sendly.live/docs/ai/mcp-tools) — all 85 tools with schemas ## CLI Install and use the Sendly CLI from the terminal. - [CLI Docs](https://sendly.live/docs/cli) - [npm: @sendly/cli](https://www.npmjs.com/package/@sendly/cli) ## OpenAPI Spec The full OpenAPI 3.0 specification for the Sendly API. - [OpenAPI spec (YAML)](https://sendly.live/openapi.yaml) ## OpenAI Function Calling Pre-built tool definitions for OpenAI Assistants and GPTs. - [OpenAI Tools (JSON)](https://sendly.live/openai-tools.json) ## Documentation - [Full documentation](https://sendly.live/docs) - [API Reference](https://sendly.live/docs/api) ## Pricing - [Pricing (Markdown)](https://sendly.live/pricing.md) - [Pricing (HTML)](https://sendly.live/pricing) ## SDKs Official libraries maintained by the Sendly team. - [Node.js](https://github.com/SendlyHQ/sendly-node) - [Python](https://github.com/SendlyHQ/sendly-python) - [Go](https://github.com/SendlyHQ/sendly-go) - [Ruby](https://github.com/SendlyHQ/sendly-ruby) - [PHP](https://github.com/SendlyHQ/sendly-php) - [Java](https://github.com/SendlyHQ/sendly-java) - [Rust](https://github.com/SendlyHQ/sendly-rust) - [.NET](https://github.com/SendlyHQ/sendly-dotnet) - [CLI](https://github.com/SendlyHQ/sendly/tree/main/packages/cli) --- > Sendly provides programmatic SMS and MMS messaging to 190+ countries. Key features include scheduled messages, batch sending (up to 1000 messages), phone verification (OTP), webhooks for delivery status, contacts management, conversations, AI classification, message templates, quiet hours compliance, and comprehensive SDK support. ## Getting Started - [Introduction](https://sendly.live/docs): Platform overview and key features - [Quickstart](https://sendly.live/docs/quickstart): Send your first SMS in 5 minutes - [Authentication](https://sendly.live/docs/auth): API key authentication with Bearer tokens - [Sandbox Testing](https://sendly.live/docs/sandbox): Test without sending real messages using magic phone numbers - [LLM Integration](https://sendly.live/docs/llms): Optimized reference for AI coding assistants ## Core API - [Send SMS](https://sendly.live/docs/sms): POST /api/v1/messages - Send a single SMS message - [Send MMS](https://sendly.live/docs/mms): POST /api/v1/messages - Send MMS with media attachments (up to 10 URLs) - [List Messages](https://sendly.live/docs/messages): GET /api/v1/messages - Retrieve message history with filtering - [Scheduled Messages](https://sendly.live/docs/scheduled): Schedule SMS for future delivery with timezone support - [Batch Messages](https://sendly.live/docs/batch): Send up to 1000 messages in a single API request - [Quiet Hours](https://sendly.live/docs/quiet-hours): Marketing messages blocked 9pm-8am recipient local time ## Contacts API - [List Contacts](https://sendly.live/docs/api#contacts): GET /api/v1/contacts - List contacts with pagination - [Create Contact](https://sendly.live/docs/api#contacts): POST /api/v1/contacts - Create a new contact - [Get Contact](https://sendly.live/docs/api#contacts): GET /api/v1/contacts/:id - Get contact details - [Update Contact](https://sendly.live/docs/api#contacts): PATCH /api/v1/contacts/:id - Update contact fields - [Delete Contact](https://sendly.live/docs/api#contacts): DELETE /api/v1/contacts/:id - Delete a contact ### List Health Contacts are automatically flagged when carrier sends return terminal bad-number errors (E001/E003), and can be proactively validated via carrier lookup before sending. Campaigns and previews skip flagged contacts; the Batch API does not (respects developer intent). - [Clean Contact List](https://sendly.live/docs/how-to/clean-contact-list): Auto-exclusion, carrier lookups, bulk override - [Deliverability](https://sendly.live/docs/concepts/deliverability): Error taxonomy (E001–E015), retry behaviour, list health - `POST /api/v1/contacts/lookup` - Trigger async carrier lookup for a list (body: `{ listId?, force? }`). Returns `{ success, alreadyRunning?, message }`. Idempotent — the same account+listId while a run is active returns `alreadyRunning: true` instead of enqueueing a duplicate. - `POST /api/v1/contacts/:id/mark-valid` - Clear the `invalidReason` flag on a single contact (user override). Stamps `userMarkedValidAt` so future re-checks won't re-flag. - `POST /api/v1/contacts/bulk-mark-valid` - Clear the flag on many contacts (body: `{ ids?: string[] }` *or* `{ listId?: string }`, max 10,000 ids). Returns `{ cleared }`. Contact fields added for list health (all nullable, all returned on GET): - `invalidReason`: one of `landline`, `invalid_number`, `non_sms_capable`, or null - `invalidatedAt`: ISO timestamp of auto-flag - `lineType`: carrier-reported line type (`mobile`, `fixed line`, `voip`, `toll free`, `pager`, etc.) - `carrierName`: carrier-reported carrier name - `lineTypeCheckedAt`: ISO timestamp of last carrier lookup - `userMarkedValidAt`: ISO timestamp of user override (if any) ## Templates API - [List Templates](https://sendly.live/docs/api#templates): GET /api/v1/templates - List user + preset templates - [Create Template](https://sendly.live/docs/api#templates): POST /api/v1/templates - Create a message template with variables - [Get Template](https://sendly.live/docs/api#templates): GET /api/v1/templates/:id - Get template details - [Update Template](https://sendly.live/docs/api#templates): PATCH /api/v1/templates/:id - Update template - [Delete Template](https://sendly.live/docs/api#templates): DELETE /api/v1/templates/:id - Delete template - [Template Presets](https://sendly.live/docs/api#templates): GET /api/v1/templates/presets - List preset templates ## Verify API (OTP) Phone number verification with one-time passwords. Perfect for 2FA, phone verification, and passwordless login. - [Verify Overview](https://sendly.live/docs/verify): Complete phone verification solution - [Send OTP](https://sendly.live/docs/verify#send): POST /api/v1/verify - Send verification code to phone number - [Check Code](https://sendly.live/docs/verify#check): POST /api/v1/verify/:id/check - Verify OTP code entered by user - [Resend OTP](https://sendly.live/docs/verify#resend): POST /api/v1/verify/:id/resend - Resend verification code - [Get Status](https://sendly.live/docs/verify#status): GET /api/v1/verify/:id - Check verification status - [Hosted Flow](https://sendly.live/docs/verify#hosted-flow): Zero-code verification UI - redirect users, we handle the rest - [Create Session](https://sendly.live/docs/verify#hosted-flow): POST /api/v1/verify/sessions - Create hosted verification session - [Validate Token](https://sendly.live/docs/verify#hosted-flow): POST /api/v1/verify/sessions/validate - Exchange token for verified phone ### Verify API Quick Reference ``` POST /api/v1/verify {"to": "+15551234567", "app_name": "MyApp", "code_length": 6, "timeout_secs": 300} POST /api/v1/verify/:id/check {"code": "123456"} POST /api/v1/verify/sessions {"success_url": "https://yourapp.com/verified?token={TOKEN}", "brand_name": "MyApp"} POST /api/v1/verify/sessions/validate {"token": "tok_xxx"} ``` ## Conversations API Thread SMS messages into conversations by phone number. Auto-created on every send/receive. Track status, unread counts, tags, and metadata. - [Conversations Overview](https://sendly.live/docs/conversations): Auto-threading, status lifecycle, webhooks - [List Conversations](https://sendly.live/docs/conversations#list): GET /api/v1/conversations - [Get Conversation](https://sendly.live/docs/conversations#get): GET /api/v1/conversations/:id - [Reply to Conversation](https://sendly.live/docs/conversations#reply): POST /api/v1/conversations/:id/messages - [Update Conversation](https://sendly.live/docs/conversations#update): PATCH /api/v1/conversations/:id - [Close/Reopen/Mark Read](https://sendly.live/docs/conversations#lifecycle): POST /api/v1/conversations/:id/close|reopen|mark-read ### Conversations Quick Reference ``` GET /api/v1/conversations - List conversations (?status=active&limit=50&offset=0) GET /api/v1/conversations/:id - Get conversation (?include_messages=true&message_limit=50) POST /api/v1/conversations/:id/messages - Reply (body: {text, mediaUrls?}) PATCH /api/v1/conversations/:id - Update (body: {metadata?, tags?}) POST /api/v1/conversations/:id/close - Close conversation POST /api/v1/conversations/:id/reopen - Reopen conversation POST /api/v1/conversations/:id/mark-read - Reset unread count ``` ## SDKs | Language | Package | Install Command | |----------|---------|-----------------| | Node.js | @sendly/node | `npm install @sendly/node` | | Python | sendly | `pip install sendly` | | Go | sendly-go | `go get github.com/SendlyHQ/sendly-go` | | Ruby | sendly | `gem install sendly` | | PHP | sendly/sendly-php | `composer require sendly/sendly-php` | | Java | live.sendly:sendly-java | Maven/Gradle (see docs) | | Rust | sendly | `cargo add sendly` | | .NET | Sendly | `dotnet add package Sendly` | | CLI | @sendly/cli | `npm install -g @sendly/cli` | | MCP Server | @sendly/mcp | `npx @sendly/mcp` (via SENDLY_API_KEY env var) | - [SDK Overview](https://sendly.live/docs/sdks): All official SDKs with installation guides and examples - [Node.js](https://sendly.live/docs/sdks#nodejs): TypeScript support, zero dependencies - [Python](https://sendly.live/docs/sdks#python): Type hints and async support, Python 3.10+ - [Go](https://sendly.live/docs/sdks#go): Context support, Go 1.21+ - [Ruby](https://sendly.live/docs/sdks#ruby): Idiomatic Ruby patterns - [Java](https://sendly.live/docs/sdks#java): Java 17+ required - [PHP](https://sendly.live/docs/sdks#php): PHP 8.1+ required - [Rust](https://sendly.live/docs/sdks#rust): Async/Tokio support - [.NET](https://sendly.live/docs/sdks#dotnet): .NET 8.0+ required ## Webhooks & Events - [Webhooks](https://sendly.live/docs/webhooks): Receive real-time delivery status callbacks - [Signature Verification](https://sendly.live/docs/webhooks#security): HMAC-SHA256 webhook signature verification - [Retry Logic](https://sendly.live/docs/webhooks#retries): Automatic retries with exponential backoff (0s, 1m, 5m, 30m, 2h, 24h) ### Webhook Payload Structure All webhook payloads use `data.object` nesting: ```json { "id": "evt_abc123", "type": "message.delivered", "api_version": "2024-01", "created": 1737283800, "livemode": true, "data": { "object": { "id": "msg_xyz789", "organization_id": "org_abc", "to": "+15551234567", "from": "+18775559876", "text": "Hello!", "status": "delivered", "direction": "outbound", "segments": 1, "credits_used": 2, "message_format": "sms", "created_at": 1737283200, "delivered_at": 1737283800 } } } ``` ### Webhook Signature Verification Every webhook request includes two security headers: - `X-Sendly-Signature`: HMAC-SHA256 signature with `sha256=` prefix - `X-Sendly-Timestamp`: Unix timestamp when the webhook was sent The HMAC is computed on `${timestamp}.${jsonPayload}` using your webhook secret. Always verify signatures and reject requests where the timestamp is older than 5 minutes (replay attack prevention). ```javascript const signedPayload = `${timestamp}.${payload}`; const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(signedPayload, 'utf8').digest('hex'); ``` ### Message Events - `message.sent` - Message accepted by carrier - `message.delivered` - Message successfully delivered - `message.failed` - Delivery failed - `message.bounced` - Invalid number - `message.retrying` - Delivery being retried - `message.received` - Inbound message received - `message.opt_out` - Recipient opted out (STOP) - `message.opt_in` - Recipient opted back in (START) ### Conversation Events - `conversation.created` - First message in a new conversation - `conversation.updated` - New message in an existing conversation ### Verification Events - `verification.created` - OTP code sent - `verification.delivered` - SMS delivered to phone - `verification.verified` - Code verified successfully - `verification.expired` - Code expired without verification - `verification.failed` - Max attempts exceeded (3 attempts allowed) - `verification.resent` - OTP code resent - `verification.delivery_failed` - SMS delivery failed ### List Health Events - `contact.auto_flagged` - A contact was automatically flagged as unsendable after a terminal carrier error (E001/E003) or a non-SMS-capable carrier lookup result. Fires once per clean→flagged transition; retries and force re-checks of already-flagged contacts do NOT re-fire. Payload includes `invalid_reason`, `source` (one of `send_failure`, `carrier_lookup`), and for send-failure sources also `message_id` and `error_code`. - `contact.marked_valid` - A contact's auto-flag was cleared via the single mark-valid endpoint. Fires only when the contact was actually flagged (no-op calls are silent). Bulk operations emit `contacts.bulk_marked_valid` instead. - `contacts.bulk_marked_valid` - One aggregate event for a bulk clear (`POST /api/v1/contacts/bulk-mark-valid`). Payload includes `cleared` (count) and `ids` (list of cleared contact IDs, truncated with `truncated: true` beyond a sane cap). Use this to sync external state after large overrides without receiving a per-contact firehose. - `contacts.lookup_completed` - Fires once per logical carrier-lookup sweep, on the terminal run (no continuation pending). Payload: `{ list_id, scope, force, processed, newly_flagged, skipped_due_to_cap, skipped_due_to_user_override, monthly_cap }`. Counts reflect the final run's slice; for full sweeps of lists >22,500 contacts, downstream can correlate by sweep ID. ## Billing & Credits - [Credits](https://sendly.live/docs/credits): Check balance and view transaction history - [Credit Packages](https://sendly.live/docs/packages): Purchase credits with volume discounts - [Pricing](https://sendly.live/pricing): Country-specific SMS pricing for 50+ countries ### Credit Pricing (1 credit = $0.01 USD) | Tier | Countries | Credits per SMS | |------|-----------|-----------------| | Domestic | US, Canada | 2 credits ($0.02) | | Tier 1 | UK, Germany, France, Australia, etc. | 8 credits ($0.08) | | Tier 2 | Spain, Italy, Brazil, Mexico, etc. | 12 credits ($0.12) | | Tier 3 | India, South Africa, Turkey, etc. | 16 credits ($0.16) | | Tier 4 | Thailand, Vietnam, Philippines, etc. | 24 credits ($0.24) | | Tier 5 | Indonesia, Pakistan, Nigeria, etc. | 48 credits ($0.48) | MMS messages cost 5 credits ($0.05) for US/CA domestic. ## Tools - [CLI](https://sendly.live/docs/cli): Command-line interface for sending SMS from terminal - [CLI Installation](https://sendly.live/docs/cli#installation): npm install -g @sendly/cli - [CLI Authentication](https://sendly.live/docs/cli#authentication): Browser login and API key auth - [CLI Commands](https://sendly.live/docs/cli#reference): Full command reference for sms, keys, credits, webhooks - [Webhook Listener](https://sendly.live/docs/cli#webhooks): Local development webhook forwarding - [MCP Server](https://sendly.live/docs/mcp): SMS for AI agents via Model Context Protocol (85 tools) - [Hosted MCP](https://mcp.sendly.live): No-install hosted server on Cloudflare's edge - [MCP Setup](https://sendly.live/docs/ai/mcp-setup): Per-platform setup (Cursor, Claude Code, Codex, Windsurf, etc.) - [MCP Tools](https://sendly.live/docs/ai/mcp-tools): All 85 tools with input/output schemas - [MCP Architecture](https://sendly.live/docs/concepts/mcp-architecture): Security model, design decisions ## Enterprise - [Enterprise API](https://sendly.live/docs/enterprise): Multi-tenant workspace management - [Enterprise Architecture](https://sendly.live/docs/concepts/enterprise): Pooled credits, workspace provisioning, bulk operations - [Provision Workspaces](https://sendly.live/docs/how-to/provision-workspaces): Create and manage agent workspaces - [Workspace Credits](https://sendly.live/docs/how-to/manage-workspace-credits): Allocate pooled credits across workspaces ## Reference - [API Reference](https://sendly.live/docs/api): Complete REST API endpoint documentation - [API Keys](https://sendly.live/docs/keys): Create, rotate, and manage API keys with scopes - [Rate Limits](https://sendly.live/docs/rate-limits): Request limits and quotas per key type - [Error Codes](https://sendly.live/docs/errors): Error response codes and troubleshooting - [Country Requirements](https://sendly.live/docs/country-requirements): Sender ID registration by country ## Complete API Endpoint Reference ### Authentication All requests require Bearer token: `Authorization: Bearer sk_live_xxx` or `sk_test_xxx` ### Messages ``` POST /api/v1/messages - Send single SMS or MMS POST /api/v1/messages/batch - Send up to 1000 messages POST /api/v1/messages/schedule - Schedule future delivery GET /api/v1/messages - List messages with pagination GET /api/v1/messages/:id - Get message details GET /api/v1/messages/scheduled - List scheduled messages DELETE /api/v1/messages/scheduled/:id - Cancel scheduled message ``` ### MMS (via Messages endpoint) ``` POST /api/v1/messages { "to": "+15551234567", "text": "Check this out!", "messageType": "transactional", "mediaUrls": ["https://example.com/image.jpg"] } ``` Supports up to 10 media URLs. Accepted formats: JPEG, PNG, GIF, BMP, WebP, MP4 (under 1MB each). ### Contacts ``` GET /api/v1/contacts - List contacts (scope: contacts:read) POST /api/v1/contacts - Create contact (scope: contacts:write) GET /api/v1/contacts/:id - Get contact details PATCH /api/v1/contacts/:id - Update contact DELETE /api/v1/contacts/:id - Delete contact POST /api/v1/contacts/lookup - Trigger async carrier lookup ({listId?, force?}) POST /api/v1/contacts/:id/mark-valid - Clear invalidReason (single contact) POST /api/v1/contacts/bulk-mark-valid - Bulk clear invalidReason ({ids?} or {listId?}) ``` ### Templates ``` GET /api/v1/templates - List user + preset templates (scope: templates:read) POST /api/v1/templates - Create template (scope: templates:write) GET /api/v1/templates/:id - Get template details PATCH /api/v1/templates/:id - Update template DELETE /api/v1/templates/:id - Delete template GET /api/v1/templates/presets - List preset templates POST /api/v1/templates/:id/publish - Publish draft template POST /api/v1/templates/:id/preview - Preview template with variables ``` ### Verify (OTP) ``` POST /api/v1/verify - Send OTP code POST /api/v1/verify/:id/check - Verify code POST /api/v1/verify/:id/resend - Resend code GET /api/v1/verify/:id - Get verification status GET /api/v1/verify - List verifications POST /api/v1/verify/sessions - Create hosted session POST /api/v1/verify/sessions/validate - Validate token ``` ### Conversations ``` GET /api/v1/conversations - List conversations GET /api/v1/conversations/:id - Get conversation (with optional messages) POST /api/v1/conversations/:id/messages - Reply to conversation PATCH /api/v1/conversations/:id - Update metadata/tags POST /api/v1/conversations/:id/close - Close conversation POST /api/v1/conversations/:id/reopen - Reopen conversation POST /api/v1/conversations/:id/mark-read - Mark as read ``` ### Webhooks ``` POST /api/v1/webhooks - Create webhook GET /api/v1/webhooks - List webhooks GET /api/v1/webhooks/:id - Get webhook details PATCH /api/v1/webhooks/:id - Update webhook DELETE /api/v1/webhooks/:id - Delete webhook POST /api/v1/webhooks/:id/test - Send test event ``` ### API Keys ``` POST /api/v1/keys - Create API key GET /api/v1/keys - List API keys GET /api/v1/keys/:id - Get key details DELETE /api/v1/keys/:id - Revoke key POST /api/v1/keys/:id/rotate - Rotate key (24h grace period) PATCH /api/v1/keys/:id/rename - Rename key ``` ### Credits ``` GET /api/v1/credits/balance - Get balance GET /api/v1/credits/transactions - Transaction history GET /api/v1/credits/packages - Available packages ``` ## Sandbox Testing Use `sk_test_*` API keys with these magic phone numbers: | Number | Behavior | |--------|----------| | +15005550000 | Always succeeds | | +15005550001 | Invalid number error | | +15005550002 | Cannot route error | | +15005550003 | Insufficient credits | | +15005550004 | Rate limited | | +15005550006 | Carrier rejected | ## Message Types (Required) | Type | Use Case | Quiet Hours | |------|----------|-------------| | `transactional` | OTPs, confirmations, alerts | 24/7 allowed | | `marketing` | Promotions, newsletters | Blocked 9pm-8am recipient time | ## Quick Start Example ```javascript import Sendly from '@sendly/node'; const client = new Sendly('sk_live_YOUR_API_KEY'); // Send SMS const message = await client.messages.send({ to: '+15551234567', text: 'Hello from Sendly!', messageType: 'transactional' }); // Send MMS const mms = await client.messages.send({ to: '+15551234567', text: 'Check this out!', messageType: 'transactional', mediaUrls: ['https://example.com/image.jpg'] }); // Send OTP const verification = await client.verify.send({ to: '+15551234567', appName: 'MyApp' }); // Verify code const result = await client.verify.check(verification.id, { code: '123456' }); ``` ## AI Features - [AI Overview](https://sendly.live/docs/ai): Classification, suggested replies, auto-labeling - [Classification API](https://sendly.live/docs/ai/classification-api): Intent + sentiment on every inbound message - [Suggested Replies](https://sendly.live/docs/ai/suggested-replies): AI-generated reply suggestions with tones - [Auto-labeling](https://sendly.live/docs/ai/auto-labeling): Automatic conversation categorization - [Drafts Workflow](https://sendly.live/docs/ai/drafts-workflow): Human-in-the-loop review before sending - [How Classification Works](https://sendly.live/docs/ai/how-classification-works): Architecture and cost model ### Labels ``` POST /api/v1/labels - Create label GET /api/v1/labels - List labels PATCH /api/v1/labels/:id - Update label DELETE /api/v1/labels/:id - Delete label POST /api/v1/conversations/:id/labels - Add label to conversation DELETE /api/v1/conversations/:id/labels/:labelId - Remove label ``` ### Drafts ``` POST /api/v1/drafts - Create draft message GET /api/v1/drafts - List drafts POST /api/v1/drafts/:id/approve - Approve and send draft POST /api/v1/drafts/:id/reject - Reject draft ``` ### Campaigns ``` POST /api/v1/campaigns - Create campaign GET /api/v1/campaigns - List campaigns GET /api/v1/campaigns/:id - Get campaign details POST /api/v1/campaigns/:id/send - Send campaign POST /api/v1/campaigns/:id/schedule - Schedule campaign POST /api/v1/campaigns/:id/preview - Preview campaign cost DELETE /api/v1/campaigns/:id - Delete campaign ``` ## Blog Engineering deep-dives, product updates, and behind-the-scenes from the Sendly team. - [Blog Index](https://sendly.live/blog): All posts - [Building a Sandbox That Actually Helps](https://sendly.live/blog/building-a-sandbox): Two-key testing model, magic phone numbers, webhook simulation - [Batch Messaging — Send to Thousands in One Request](https://sendly.live/blog/batch-messaging): CSV upload, per-recipient personalization, validation pipeline, dry run - [Templates and the Art of Not Repeating Yourself](https://sendly.live/blog/templates): Variables, presets, SMS segment calculation, phone preview - [Hosted Verification — Let Sendly Handle the UI](https://sendly.live/blog/hosted-verification): Session-based flow, white-label branding, token validation - [Introducing Teams — Collaborate on SMS at Scale](https://sendly.live/blog/introducing-teams): Organizations, roles, shared API keys, CLI support - [OpenClaw + Sendly on Cloudflare](https://sendly.live/blog/openclaw-cloudflare): One-click AI agent with SMS on Cloudflare Containers - [Deploy OpenClaw + Sendly on Fly.io](https://sendly.live/blog/openclaw-fly-deploy): Step-by-step Fly.io deployment guide ## Contact - Website: https://sendly.live - Documentation: https://sendly.live/docs - Dashboard: https://sendly.live/dashboard