Relay SMS Platform
Getting Started

Development Setup

Set up your local development environment with SMS-dev, Relay's local SMS testing server that acts like "Mailtrap for SMS". Test your SMS integration without sending real messages or incurring costs.

Overview

The Relay development environment includes:

  • SMS-dev server: Local API server that mimics the Relay SMS API
  • Virtual Phone UI: Web interface to simulate receiving SMS messages
  • Relay CLI: Command-line tools for managing your development workflow
  • Mock data: Realistic test data without real SMS charges

Prerequisites

Before you begin:

  • Node.js 16+ installed
  • A Relay account (for production API keys)
  • Terminal access

Quick Setup

1. Install Relay CLI

TerminalCode
npm install -g @relay/cli

2. Verify Installation

TerminalCode
relay --version # Should show version 0.0.1 or later

3. Start Development Environment

TerminalCode
relay dev

This command will:

  • Start the SMS-dev API server on port 4001
  • Launch the virtual phone UI on port 4000
  • Display connection details

Expected output:

Code
Starting the local development environment... SMS-dev Server API: http://localhost:4001 Virtual Phone UI: http://localhost:4000 Development environment ready! Send test messages to: http://localhost:4001/v1/messages View virtual phones at: http://localhost:4000

Configuration

Create Configuration File

Generate a relay.json configuration file:

TerminalCode
relay config init

This creates a relay.json file in your project:

JSONCode
{ "project": { "name": "My SMS App", "environment": "development" }, "smsDev": { "apiPort": 4001, "uiPort": 4000, "webhookUrl": "http://localhost:3000/webhook", "verbose": false, "startUI": true, "cors": { "enabled": true, "origins": ["*"] }, "logging": { "enabled": true, "level": "info" } } }

Configuration Options

OptionDescriptionDefault
apiPortSMS-dev API server port4001
uiPortVirtual phone UI port4000
webhookUrlYour app's webhook endpoint-
verboseEnable detailed loggingfalse
startUILaunch virtual phone UItrue

Environment Variables

Override configuration with environment variables:

TerminalCode
# .env file SMS_DEV_API_PORT=4001 SMS_DEV_UI_PORT=4000 SMS_DEV_WEBHOOK_URL=http://localhost:3000/webhook SMS_DEV_VERBOSE=true SMS_DEV_NO_UI=false

Using the Development Environment

1. Update Your API Endpoint

Point your application to the local development server:

JavascriptCode
// Use environment variable — RELAY_API_BASE_URL is the origin without /v1 // (the SDK and route paths append /v1/ themselves). const API_BASE_URL = process.env.NODE_ENV === 'production' ? (process.env.RELAY_API_BASE_URL || 'https://api.relay.works') : 'http://localhost:4001';

2. Use Development API Key

SMS-dev accepts any API key for testing:

JavascriptCode
// Any key works in development const API_KEY = 'rly_dev_test_key_12345'; // Or use a real key for testing against production const API_KEY = process.env.RELAY_API_KEY;

3. Send Test Messages

TerminalCode
curl -X POST http://localhost:4001/v1/messages \ -H "x-api-key: rly_dev_test_key" \ -H "Content-Type: application/json" \ -d '{ "to": "+15551234567", "message": "Hello from SMS-dev!" }'

4. View Messages in UI

  1. Open http://localhost:4000 in your browser
  2. You'll see the virtual phone interface
  3. Sent messages appear instantly
  4. Simulate incoming messages by typing responses

Development Workflow

Typical Development Flow

  1. Start environment:

    TerminalCode
    relay dev
  2. Configure your app to use http://localhost:4001

  3. Send test messages from your application

  4. View results in the virtual phone UI at http://localhost:4000

  5. Test webhooks by configuring your webhook endpoint

  6. Iterate quickly without SMS costs or delays

Example Application Setup

Node.js/Express App

JavascriptCode
// app.js const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); // Configure for development vs production const API_BASE = process.env.NODE_ENV === 'production' ? (process.env.RELAY_API_BASE_URL || 'https://api.relay.works') : 'http://localhost:4001'; const RELAY_API_KEY = process.env.RELAY_API_KEY || 'rly_dev_test_key'; // Send SMS endpoint app.post('/send-sms', async (req, res) => { const { to, message } = req.body; try { const response = await axios.post( `${API_BASE}/v1/messages`, { to, message }, { headers: { 'x-api-key': RELAY_API_KEY, 'Content-Type': 'application/json' } } ); res.json({ success: true, messageId: response.data.id }); } catch (error) { res.status(500).json({ success: false, error: error.response?.data?.message || error.message }); } }); // Webhook endpoint for receiving SMS events app.post('/webhook', (req, res) => { const { event, data } = req.body; console.log(`Received ${event}:`, data); if (event === 'message.received') { console.log(`New SMS from ${data.from}: ${data.message}`); } res.status(200).send('OK'); }); app.listen(3000, () => { console.log('App running on http://localhost:3000'); console.log('Configure SMS-dev webhook: http://localhost:3000/webhook'); });

Next.js App

JavascriptCode
// pages/api/send-sms.js export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } const { to, message } = req.body; const apiUrl = process.env.NODE_ENV === 'production' ? 'https://api.relay.works/v1' : 'http://localhost:4001/v1'; const apiKey = process.env.RELAY_API_KEY || 'rly_dev_test_key'; try { const response = await fetch(`${apiUrl}/messages`, { method: 'POST', headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' }, body: JSON.stringify({ to, message }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.message); } res.json({ success: true, messageId: data.id }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } } // pages/api/webhook.js export default function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } const { event, data } = req.body; console.log(`Webhook received ${event}:`, data); // Handle different event types switch (event) { case 'message.received': console.log(`New SMS from ${data.from}: ${data.message}`); break; case 'message.delivered': console.log(`Message ${data.id} delivered`); break; case 'message.failed': console.log(`Message ${data.id} failed: ${data.failure_reason}`); break; } res.status(200).json({ received: true }); }

Virtual Phone UI Features

Main Interface

The virtual phone UI at http://localhost:4000 provides:

  • Message history: See all sent and received messages
  • Phone number simulator: Create mock phone numbers
  • Conversation view: Thread messages by phone number
  • Message composer: Send responses to test two-way SMS
  • Real-time updates: Messages appear instantly

Mock Phone Numbers

Create virtual phone numbers for testing:

TerminalCode
# Via CLI relay sms-dev mock-phone create --phone +15551234567 --name "Test User" # List mock phones relay sms-dev mock-phone list # Delete mock phone relay sms-dev mock-phone delete --phone +15551234567

Simulating Incoming Messages

  1. Open the virtual phone UI
  2. Select a phone number
  3. Type a message in the response field
  4. Click "Send" to simulate an incoming SMS
  5. Your webhook will receive the message.received event

Advanced Configuration

Custom Ports

Run on different ports to avoid conflicts:

TerminalCode
relay dev --api-port 4101 --ui-port 4100

Disable UI

Run only the API server:

TerminalCode
relay dev --no-ui

Verbose Logging

Enable detailed logging:

TerminalCode
relay dev --verbose

Custom Webhook URL

Configure your app's webhook endpoint:

TerminalCode
relay dev --webhook-url http://localhost:3000/webhook

CLI Commands

Core Commands

TerminalCode
# Start development environment relay dev # Check status relay status # Show configuration relay config show # Initialize configuration relay config init

SMS-dev Specific Commands

TerminalCode
# Show SMS-dev help relay sms-dev # Check SMS-dev status relay sms-dev status # Stop SMS-dev server relay sms-dev stop # Create mock phone relay sms-dev mock-phone create --phone +15551234567 --name "Test" # List conversations relay sms-dev conversations list # Export message data relay sms-dev export messages --format json

Testing Webhooks

Setup Webhook Endpoint

Configure SMS-dev to send webhooks to your app:

  1. In relay.json:

    JSONCode
    { "smsDev": { "webhookUrl": "http://localhost:3000/webhook" } }
  2. Via command line:

    TerminalCode
    relay dev --webhook-url http://localhost:3000/webhook
  3. Via environment variable:

    TerminalCode
    SMS_DEV_WEBHOOK_URL=http://localhost:3000/webhook relay dev

Webhook Events

SMS-dev sends the same webhook events as production:

JavascriptCode
// Example webhook payload { "event": "message.received", "data": { "id": "msg_dev_12345", "to": "+15559876543", "from": "+15551234567", "message": "Hello from virtual phone!", "status": "received", "created_at": "2024-01-15T10:30:00Z" } }

Testing Webhook Handler

JavascriptCode
// Test your webhook handler app.post('/webhook', (req, res) => { const { event, data } = req.body; console.log('Webhook received:', { event, messageId: data.id }); // Your webhook logic here switch (event) { case 'message.received': handleIncomingMessage(data); break; case 'message.delivered': updateMessageStatus(data.id, 'delivered'); break; case 'message.failed': handleFailedMessage(data); break; } res.status(200).send('OK'); });

Production vs Development

Key Differences

FeatureDevelopment (SMS-dev)Production (Relay)
API Endpointhttp://localhost:4001https://api.relay.works
SMS DeliverySimulatedReal SMS sent
Phone NumbersMock/virtualReal purchased numbers
CostsFreePay per message
API KeysAny key worksReal API keys required
Rate LimitsNone100 req/min per key

Environment Switching

Use environment variables to switch easily:

JavascriptCode
// config.js const config = { development: { apiUrl: 'http://localhost:4001/v1', apiKey: 'rly_dev_test_key' }, production: { apiUrl: 'https://api.relay.works/v1', apiKey: process.env.RELAY_API_KEY } }; export default config[process.env.NODE_ENV || 'development'];

Troubleshooting

Common Issues

Port Already in Use

TerminalCode
# Error: Port 4001 already in use relay dev --api-port 4101 --ui-port 4100

Can't Connect to SMS-dev

  1. Check if SMS-dev is running: relay status
  2. Verify correct ports in your app configuration
  3. Check firewall settings

Webhooks Not Working

  1. Verify webhook URL is correct
  2. Check your app is running and accessible
  3. Look at SMS-dev logs: relay dev --verbose

Virtual Phone UI Not Loading

  1. Check UI port is not blocked: http://localhost:4000
  2. Try different port: relay dev --ui-port 4100
  3. Disable UI and use CLI: relay dev --no-ui

Getting Help

TerminalCode
# Show all available commands relay --help # Show SMS-dev specific help relay sms-dev --help # Check system status relay status # Show current configuration relay config show

Performance Testing

SMS-dev includes performance testing tools:

TerminalCode
# Load test with 100 messages, 5 concurrent users relay sms-dev perf load-test --messages 100 --users 5 # View performance statistics relay sms-dev perf stats

Data Export

Export test data for analysis:

TerminalCode
# Export messages as JSON relay sms-dev export messages --format json --output messages.json # Export conversations as CSV relay sms-dev export conversations --format csv --output conversations.csv

IDE Integration

VS Code Setup

  • REST Client - Test API endpoints directly in VS Code
  • DotENV - Syntax highlighting for .env files

Create REST Client File

Create api-test.http for testing:

Code
### Variables @baseUrl = http://localhost:4001/v1 @apiKey = rly_dev_test_key @phoneNumber = +15559876543 ### Test Connection GET {{baseUrl}}/user/me x-api-key: {{apiKey}} ### Send SMS POST {{baseUrl}}/messages x-api-key: {{apiKey}} Content-Type: application/json { "to": "+15551234567", "message": "Hello from VS Code!" } ### List Messages GET {{baseUrl}}/messages?limit=5 x-api-key: {{apiKey}}

Switch to production by changing @baseUrl to https://api.relay.works/v1 and using a real API key.

Troubleshooting

Port Already in Use

Problem: Error message "Port 4001 already in use"

Solutions:

TerminalCode
# Check what's using the ports lsof -i :4001 lsof -i :4000 # Use different ports relay dev --api-port 4101 --ui-port 4100

Can't Connect to SMS-dev

Problem: Application can't reach the local development server

Solutions:

  1. Check if SMS-dev is running:

    TerminalCode
    relay status
  2. Verify correct ports in your app configuration:

    JavascriptCode
    const API_URL = 'http://localhost:4001/v1'; // Check port matches
  3. Check firewall settings - ensure ports 4000 and 4001 are allowed

  4. Restart SMS-dev with verbose logging:

    TerminalCode
    relay dev --verbose

Webhooks Not Working

Problem: Webhook events not reaching your application

Solutions:

  1. Verify webhook URL is correct and accessible:

    TerminalCode
    # Test if your webhook endpoint is reachable curl -X POST http://localhost:3000/webhook \ -H "Content-Type: application/json" \ -d '{"event":"test","data":{}}'
  2. Check your app is running and listening on the correct port

  3. View SMS-dev logs for webhook delivery attempts:

    TerminalCode
    relay dev --verbose
  4. Ensure webhook handler responds with 200 status:

    JavascriptCode
    app.post('/webhook', (req, res) => { console.log('Webhook received:', req.body); res.status(200).send('OK'); // Must respond with 200 });

Virtual Phone UI Not Loading

Problem: http://localhost:4000 won't load

Solutions:

  1. Check UI port is not blocked:

    TerminalCode
    lsof -i :4000
  2. Try different port:

    TerminalCode
    relay dev --ui-port 4100
  3. Disable UI and use CLI only:

    TerminalCode
    relay dev --no-ui
  4. Check browser console for errors (F12 in most browsers)

Environment Variable Issues

Problem: Variables not loading correctly

Solutions:

  1. Verify .env file is in project root:

    TerminalCode
    ls -la .env
  2. Check file syntax (no spaces around =):

    TerminalCode
    # ✅ Correct RELAY_API_KEY=rly_sk_your_key # ❌ Wrong RELAY_API_KEY = rly_sk_your_key
  3. Restart your application after .env changes

  4. Debug environment loading:

    JavascriptCode
    require('dotenv').config({ debug: true });

SMS-dev Won't Start

Problem: relay dev command fails or crashes

Solutions:

  1. Update Node.js to version 16 or higher:

    TerminalCode
    node --version
  2. Reinstall Relay CLI:

    TerminalCode
    npm uninstall -g @relay/cli npm install -g @relay/cli
  3. Clear npm cache:

    TerminalCode
    npm cache clean --force
  4. Check for port conflicts (see "Port Already in Use" above)

Next Steps

Now that your development environment is set up:

  1. Build your first SMS feature using the local API
  2. Test webhook handling with the virtual phone UI
  3. Iterate quickly without SMS costs
  4. Deploy to production using real API keys

Related Documentation:

Last modified on