sms compliance

Sent logo
Sent TeamMar 8, 2026 / sms compliance / Martinique

Martinique SMS Guide: Compliance, Regulations & API Integration 2025

Complete Martinique SMS guide covering GDPR compliance, ARCEP regulations, French CNIL requirements, operator details, and API integration for +596 numbers.

Martinique SMS Guide: Compliance, Regulations & Best Practices

Send SMS messages to Martinique (+596) while maintaining full compliance with French telecommunications regulations. This comprehensive guide covers ARCEP regulations, GDPR and CNIL requirements, mobile number formats (0696/0697 prefixes), operator-specific details for Orange Caraïbe, SFR Caraïbe, and Digicel, API integration examples, and 2025 legislative updates affecting SMS marketing in the French Caribbean territory.

Martinique (France) SMS Market Overview

Locale name:Martinique (France)
ISO code:MQ
RegionNorth America
Mobile country code (MCC)340
Dialing Code+596

Market Conditions: As an overseas department of France, Martinique follows French telecommunications standards and regulations. The mobile market features four major operators: Orange Caraïbe, SFR Caraïbe, Digicel, and Free Caraïbe (newer entrant with competitive rates). Outremer Telecom (La Poste Mobile Caraïbe) also operates in the market.

Market Statistics (DataReportal Digital 2025, nPerf 2024):

  • Population: 342,000 (January 2025)
  • Mobile connections: 638,000 (187% of population, reflecting multiple SIMs per user)
  • Internet penetration: 64.6% (221,000 users)
  • Mobile broadband: 95.9% of connections use 3G/4G/5G networks
  • Network performance: Average mobile download speed 56.5 Mb/s

Operator Performance (nPerf Mobile Awards 2024, ARCEP QoS Audit July 2024):

  • Orange Caraïbe: #1 operator (6th consecutive year per ARCEP), 64.0 Mb/s download, 14.1 Mb/s upload, best overall quality of service
  • SFR Caraïbe: 53.4 Mb/s download, 14.7 Mb/s upload (best upload speeds)
  • Digicel: 46.8 Mb/s download, 11.2 Mb/s upload
  • Free Caraïbe: 59.3 Mb/s download, 9.4 Mb/s upload
  • Outremer Télécom: Strong performance on internet uses, nearly comparable to Orange

SMS Pricing (Sent.dm Pricing 2025): International API providers charge $0.1319–$0.1401 per SMS: Sinch ($0.1319), Plivo ($0.1359), Twilio ($0.1401). High-volume senders (10,000+ messages/month) can negotiate 15–30% discounts. Local operators offer competitive bundled rates for domestic SMS.

On February 18, 2025, 5G became accessible in Martinique with Orange and SFR Caraïbe launching their offerings. According to an ARCEP survey published in July 2024, Orange is the #1 mobile network in the Antilles-Guyane region for the 6th consecutive time.

While OTT messaging apps like WhatsApp are popular for personal communications, SMS remains crucial for business communications, notifications, and authentication purposes due to its reliability and universal reach.


Key SMS Features and Capabilities in Martinique (France)

Martinique supports standard SMS features as part of the French telecommunications infrastructure, though with some limitations on advanced features like two-way messaging and concatenation.

Two-way SMS Support

Two-way SMS is not supported in Martinique through major SMS providers. This limitation stems from carrier infrastructure restrictions and API provider routing configurations in the French Caribbean territories. Businesses should design their messaging strategies around one-way communications only.

Alternative Solutions for Two-Way Communication:

  • Implement web-based response mechanisms with unique URLs in SMS messages
  • Use dedicated customer service numbers for voice callbacks
  • Deploy WhatsApp Business API for bidirectional messaging needs
  • Create SMS-triggered email response workflows for non-urgent inquiries

Concatenated Messages (Segmented SMS)

Support: Concatenated messaging is not supported in Martinique.

Technical Explanation: Caribbean operators often lack the infrastructure to support User Data Header (UDH) concatenation protocols required for linking multiple SMS segments. When concatenation is unsupported, messages exceeding standard length are either truncated or delivered as separate, unlinked messages.

Impact and Message Length Guidelines:

  • GSM-7 encoding: Maximum 160 characters per message
  • Unicode (UTF-16) encoding: Maximum 70 characters per message
  • Messages exceeding these limits will be truncated or fail delivery
  • Each message counts as one billable unit

Handling Long Messages:

  • Design messages to fit within 160 characters (GSM-7) or 70 characters (Unicode)
  • Use URL shorteners to reduce character count
  • Split content across multiple campaigns rather than single long messages
  • Implement "Part 1/2" manual indicators if multiple messages required
  • Test all messages before bulk deployment to verify delivery

Encoding considerations: Standard GSM-7 encoding is recommended for optimal character usage and compatibility.

MMS Support

MMS messages are automatically converted to SMS with an embedded URL link to access the multimedia content. This ensures that rich media content can still be shared while maintaining compatibility with all devices.

Example MMS-to-SMS Conversion: Recipient receives: "You have received multimedia content. View here: https://mms.provider.com/view/abc123" The URL typically expires after 7-30 days depending on provider policies.

Recipient Phone Number Compatibility

Number Portability

Number portability is available in Martinique. Mobile Number Portability (MNP) was launched in 2006 and follows a 10-day porting process regulated by ARCEP Decision 2006. This means customers can switch operators while keeping their phone numbers. Businesses should regularly update their prefix databases, use asynchronous validation, and implement graceful error handling to manage number portability effectively.

Implementation Best Practices:

typescript
// Example: Graceful number portability handling
interface NumberValidation {
  isValid: boolean;
  isMobile: boolean;
  originalOperator: string | null;
  lastUpdated: Date;
}

async function validateMartiniqueNumber(phoneNumber: string): Promise<NumberValidation> {
  const e164Format = phoneNumber.replace(/[^\d+]/g, '');

  // Validate format: +596 696/697 XXX XXX
  const mobileRegex = /^\+596(696|697)\d{6}$/;

  if (!mobileRegex.test(e164Format)) {
    return { isValid: false, isMobile: false, originalOperator: null, lastUpdated: new Date() };
  }

  // Note: Due to number portability, prefix-based operator detection is unreliable
  // Implement HLR (Home Location Register) lookup for accurate carrier identification
  return {
    isValid: true,
    isMobile: true,
    originalOperator: 'Use HLR lookup for current operator',
    lastUpdated: new Date()
  };
}

Sending SMS to Landlines

Sending SMS to landline numbers is not possible in Martinique. Attempts to send messages to landline numbers will result in a failed delivery with a 400 response error (code 21614), and no charges will be incurred.

Compliance and Regulatory Guidelines for SMS in Martinique (France)

As an overseas department of France, Martinique follows French telecommunications regulations and GDPR requirements. The primary regulatory authority is ARCEP (Autorité de Régulation des Communications électroniques et des Postes), with additional oversight from CNIL (Commission Nationale de l'Informatique et des Libertés) for data privacy matters.

Explicit Consent Requirements:

  • Written consent must be obtained before sending marketing messages to consumers (B2C)
  • Article L34-5 of the French Postal and Electronic Communications Code (CPCE) prohibits direct prospecting via automated electronic communication systems without prior consent
  • Consent must be freely given, specific, informed, and unambiguous
  • Documentation of consent must include timestamp, source, and scope
  • Separate consent required for different types of communications
  • B2B marketing is not subject to these restrictions

Customer Exception:

  • Opt-out consent applies when the recipient is already a customer and the marketing concerns similar products or services provided by the same company
  • Non-commercial prospecting is exempt from prior consent requirements

2024 CNIL Enforcement Context (CNIL Sanctions 2024):

  • CNIL imposed €525,000 fine to HUBSIDE.STORE (April 4, 2024) for campaigns using deceptive forms that failed to collect valid consent per Article L34-5 CPCE
  • CNIL issued 87 sanctions totaling €55,212,400 in 2024, with commercial prospecting violations being a priority enforcement area
  • Orange fined €50 million (November 14, 2024) for cookie consent violations and inadequate commercial prospecting practices
  • CNIL has made consent validation in loyalty schemes and marketing data reuse a priority topic for 2024-2025

Common Compliance Violations and Consequences:

  1. Lack of valid consent: Fines €15,000–€900,000 (e.g., €525,000 to HUBSIDE.STORE, €900,000 to marketing company in May 2025)
  2. Pre-checked consent boxes: Violates GDPR Article 4(11) requirement for "unambiguous" consent
  3. Insufficient consent documentation: Must maintain proof with timestamp, source, and scope for minimum 3 years
  4. Consent bundling: Requesting consent for multiple purposes in single checkbox invalidates consent
  5. Failure to honor opt-out requests: €10,000–€20,000 fines plus injunctions

Technical Implementation for Consent Collection:

typescript
// Example: GDPR-compliant consent collection
interface ConsentRecord {
  userId: string;
  consentType: 'marketing_sms' | 'transactional_sms' | 'promotional_offers';
  granted: boolean;
  timestamp: Date;
  source: string;  // e.g., 'website_signup', 'mobile_app', 'in_store'
  ipAddress: string;
  userAgent: string;
  scope: string;  // Detailed description of what was consented to
  expiryDate: Date | null;
}

async function recordConsent(consent: ConsentRecord): Promise<void> {
  // Store consent with full audit trail
  await database.consents.create({
    ...consent,
    recordedAt: new Date(),
    gdprCompliant: validateConsentCompliance(consent)
  });

  // Generate consent confirmation
  if (consent.granted) {
    await sendConsentConfirmation(consent.userId, consent.scope);
  }
}

function validateConsentCompliance(consent: ConsentRecord): boolean {
  // Ensure consent meets GDPR Article 4(11) requirements
  return consent.timestamp !== null &&
         consent.source !== '' &&
         consent.scope !== '' &&
         !consent.scope.includes('bundled');  // No bundled consents
}

Best Practices for Consent Collection:

  • Use clear, unchecked opt-in boxes (pre-checked boxes violate GDPR)
  • Maintain detailed consent records with timestamp, source, IP address, and scope
  • Provide transparent information about message frequency and content
  • Enable easy access to privacy policies and terms of service
  • Implement double opt-in for marketing SMS to strengthen proof of consent
  • Store consent records for minimum 3 years after withdrawal

HELP/STOP and Other Commands

  • Required Keywords: STOP, ARRETER, DESABONNEMENT must be supported
  • Language Requirements: Both French and Creole support recommended
  • Response Time: Immediate acknowledgment required for opt-out requests
  • Command Processing: Must be case-insensitive and support common variations

Implementation Example:

typescript
// Example: Opt-out command processing
const OPT_OUT_KEYWORDS = [
  'STOP', 'ARRETER', 'DESABONNEMENT', 'STOP SMS', 'UNSUBSCRIBE',
  'ARRÊTER', 'DÉSABONNEMENT', 'CANCEL', 'ANNULER'
];

async function processInboundSMS(from: string, body: string): Promise<void> {
  const normalizedBody = body.trim().toUpperCase()
    .normalize('NFD').replace(/[\u0300-\u036f]/g, ''); // Remove accents

  // Check for opt-out keywords (including misspellings)
  const isOptOut = OPT_OUT_KEYWORDS.some(keyword =>
    normalizedBody.includes(keyword) ||
    levenshteinDistance(normalizedBody, keyword) <= 2  // Allow 2-char typos
  );

  if (isOptOut) {
    await processOptOut(from);
    await sendOptOutConfirmation(from);
    return;
  }

  // Handle other commands (HELP, CONTACT, etc.)
  if (normalizedBody.includes('HELP') || normalizedBody.includes('AIDE')) {
    await sendHelpInformation(from);
  }
}

async function processOptOut(phoneNumber: string): Promise<void> {
  await database.optOuts.create({
    phoneNumber,
    timestamp: new Date(),
    source: 'sms_reply',
    permanent: true
  });

  // Report to 33700 spam service if required
  await notifySpamService(phoneNumber);
}

Do Not Call / Do Not Disturb Registries

Important: Bloctel Does NOT Apply to SMS

  • France's Bloctel service is a do-not-call registry for voice calls ONLY
  • Bloctel does NOT cover SMS or MMS messages
  • Businesses do not need to screen SMS numbers against Bloctel

SMS-Specific Opt-Out Mechanisms:

  • STOP SMS System: Recipients can send "STOP" to the sender's number to opt out. Companies must confirm receipt and delete the information from their database
  • CONTACT Command: Recipients can text "CONTACT" to receive customer service contact information
  • 33700 Reporting Service: Recipients can forward unwanted SMS to 33700 (free for Bouygues Telecom, Orange France, and SFR users). Operators will deal directly with senders of unsolicited messages. Implementation: Businesses should monitor 33700 reports and immediately remove flagged numbers
  • Maintain internal suppression lists for opted-out numbers
  • Honor opt-out requests immediately (within 24 hours maximum, preferably real-time)

2024 Legislative Updates:

  • New law adopted in 2024 (effective January 2026) raises maximum fines to €500,000 or up to 20% of annual turnover
  • Law enables anti-spam filters for SMS messages, mirroring email controls, to reduce phishing and fraud
  • From August 2026, cold calling will be prohibited by default (currently opt-out via Bloctel)
  • Transition Planning: Businesses should audit consent records, implement explicit opt-in collection, and prepare for stricter enforcement by Q1 2026

Time Zone Sensitivity

  • Time Zone: Atlantic Standard Time (AST), UTC-4
  • Daylight Saving: Not observed in Martinique; AST remains constant year-round
  • Permitted Hours: 8:00 AM to 10:00 PM AST (12:00 PM to 2:00 AM UTC)
  • Restricted Days: No marketing messages on Sundays and public holidays
  • Emergency Messages: Time restrictions don't apply to urgent notifications
  • Queue Management: Messages outside permitted hours should be queued for next available window

Timezone Conversion Example:

typescript
import { DateTime } from 'luxon';

function canSendSMS(scheduledTime: Date): boolean {
  const martiniqueTZ = 'America/Martinique';  // UTC-4
  const time = DateTime.fromJSDate(scheduledTime).setZone(martiniqueTZ);

  // Check if Sunday or public holiday
  if (time.weekday === 7 || isPublicHoliday(time)) {
    return false;
  }

  // Check permitted hours: 8 AM - 10 PM AST
  const hour = time.hour;
  return hour >= 8 && hour < 22;
}

function getNextAvailableSlot(requestedTime: Date): Date {
  let slot = DateTime.fromJSDate(requestedTime).setZone('America/Martinique');

  while (!canSendSMS(slot.toJSDate())) {
    if (slot.hour < 8) {
      slot = slot.set({ hour: 8, minute: 0 });
    } else if (slot.hour >= 22) {
      slot = slot.plus({ days: 1 }).set({ hour: 8, minute: 0 });
    } else if (slot.weekday === 7) {
      slot = slot.plus({ days: 1 }).set({ hour: 8, minute: 0 });
    }
  }

  return slot.toJSDate();
}

Phone Numbers Options and SMS Sender Types for in Martinique (France)

Martinique Phone Number Format

Martinique uses a 10-digit numbering system regulated by ARCEP. Understanding the format is essential for SMS routing and validation:

Number Structure:

  • Landlines: 0596 XXX XXX (national) or +596 596 XXX XXX (international)
  • Mobile phones: 0696 XXX XXX or 0697 XXX XXX (national) or +596 696 XXX XXX / +596 697 XXX XXX (international)
  • Mobile prefixes 696 and 697 identify cellular numbers

E.164 Format:

  • Use +596XXXXXXXXX format for international compatibility
  • Example mobile: +596696123456
  • Example landline: +596596123456

Key Points:

  • The prefix '596' appears twice for landlines (country code + area code)
  • Mobile Number Portability allows customers to keep numbers when switching operators
  • Always validate numbers match the 0696/0697 pattern for mobile SMS delivery

Validation Regex Patterns:

typescript
// Martinique mobile number validation
const MARTINIQUE_MOBILE_PATTERNS = {
  // E.164 international format
  e164: /^\+596(696|697)\d{6}$/,

  // National format with leading zero
  national: /^0(696|697)\d{6}$/,

  // Flexible format (accepts spaces, dashes, parentheses)
  flexible: /^(\+596|0)?\s*[-.]?\s*(696|697)\s*[-.]?\s*(\d{3})\s*[-.]?\s*(\d{3})$/
};

function validateMartiniqueNumber(input: string): { valid: boolean; e164: string | null } {
  // Remove all non-digit characters except leading +
  const cleaned = input.replace(/[^\d+]/g, '');

  // Try E.164 format first
  if (MARTINIQUE_MOBILE_PATTERNS.e164.test(cleaned)) {
    return { valid: true, e164: cleaned };
  }

  // Try national format
  const nationalMatch = cleaned.match(MARTINIQUE_MOBILE_PATTERNS.national);
  if (nationalMatch) {
    const e164 = `+596${cleaned.substring(1)}`;  // Remove leading 0, add +596
    return { valid: true, e164 };
  }

  return { valid: false, e164: null };
}

// Example usage
const examples = [
  '+596696123456',    // Valid E.164
  '0696 12 34 56',    // Valid national
  '+596 697-123-456', // Valid with formatting
  '+596596123456',    // Invalid (landline)
  '+596695123456'     // Invalid (wrong prefix)
];

examples.forEach(num => {
  const result = validateMartiniqueNumber(num);
  console.log(`${num}: ${result.valid ? result.e164 : 'Invalid'}`);
});

Alphanumeric Sender ID

Operator network capability: Supported with dynamic usage allowed Registration requirements: No pre-registration required Sender ID preservation: Sender IDs are generally preserved as sent

Formatting Rules:

  • Length: 3-11 characters
  • Allowed characters: A-Z, a-z, 0-9, and spaces
  • Restrictions: Cannot be all numeric (would be confused with phone numbers)
  • Case sensitivity: Preserved but displayed as sent by device
  • Special characters: Avoid punctuation; may be stripped by carriers

Effective vs Ineffective Examples:

Effective Sender IDsWhy It WorksIneffective Sender IDsWhy It Fails
YourBankClear, recognizable brandYOURBANK123Too long, includes numbers
AcmeCorpProfessional, conciseAcme CorporationExceeds 11 characters
AlertSysDescriptive purposeAlert!Special character removed
MaVilleLocal language (French)My-CompanyHyphen may be stripped
ShopDealClear commercial intent123456All numeric (invalid)

Best Practices:

  • Use your brand name or recognizable abbreviation
  • Keep under 11 characters for guaranteed delivery
  • Test sender IDs across all major operators before bulk campaigns
  • Consistent sender IDs build trust and improve engagement rates

Long Codes

Domestic vs. International: International long codes supported; domestic not available Sender ID preservation: Original sender ID preserved for international numbers Provisioning time: Immediate for international numbers Use cases: Transactional messages, alerts, and notifications

Short Codes

Support: Not supported in Martinique Provisioning time: N/A Use cases: N/A


Restricted SMS Content, Industries, and Use Cases

Prohibited Content (French CPCE Article L34-5, ARCEP regulations):

  • Gambling and betting services (unless licensed by ANJ - Autorité Nationale des Jeux)
  • Adult content or explicit material (French Penal Code Article 227-24)
  • Cryptocurrency promotions (PACTE Law 2019, AMF restrictions)
  • Unauthorized financial services (ACPR licensing required)
  • Phishing, fraud, or impersonation attempts (criminal offense)

Enforcement: Violations reported to ARCEP and 33700 spam service result in immediate sender blocking, fines up to €375,000, and potential criminal prosecution.

Regulated Industries:

  • Financial services: Must include ACPR license number and regulatory disclaimers per Article L561-1 Monetary and Financial Code
  • Healthcare messages: Must maintain patient confidentiality per GDPR Article 9 (special category data) and French Public Health Code
  • Insurance services: Must include ORIAS registration number and license information per Insurance Code Article L512-1
  • Pharmaceutical promotions: Require ANSM approval, must include health warnings per Public Health Code Article L5122-6

Compliant vs Non-Compliant Message Examples:

IndustryCompliant ExampleNon-Compliant Example
Financial"Votre banque XYZ (ACPR 12345): Solde disponible 500€. Questions? 0596-XX-XX-XX""URGENT! Gagnez 5000€ maintenant! Cliquez ici:"
Healthcare"Rappel RDV: Dr. Martin, 15/06 10h. Annuler? Répondez OUI""Vos résultats médicaux: Diabète Type 2 confirmé."
Insurance"AssurPlus (ORIAS 123456): Votre devis auto prêt. Voir: lien-court.fr/xyz""Meilleure assurance! -50% aujourd'hui!"

Content Filtering

Known Carrier Filters:

  • URLs from unknown domains may be blocked (Orange, SFR implement URL reputation checks)
  • Messages containing certain keywords may be filtered ("gratuit," "urgent," "cliquez")
  • High-volume identical messages may be flagged as spam (>1000 identical messages/hour)
  • Suspicious patterns trigger 33700 spam service review

Testing Best Practices:

  • Use carrier-approved URL shorteners (bit.ly, tinyurl.com with verified accounts)
  • Avoid excessive punctuation (!!!), ALL CAPS, or urgency tactics
  • Maintain consistent sending patterns (avoid sudden volume spikes)
  • Include clear business identification and opt-out instructions
  • Test messages with all carriers before bulk deployment
  • Monitor delivery rates by operator; <95% suggests filtering issues

Best Practices for Sending SMS in Martinique (France)

Messaging Strategy

  • Keep messages under 160 characters when possible
  • Include clear call-to-actions
  • Maintain consistent brand voice
  • Use personalization thoughtfully

Message Examples and Use Cases:

  1. Transactional (OTP): "Votre code BanqueXYZ: 847392. Valide 5 min. Ne partagez pas." (56 chars)
  2. Appointment Reminder: "Rappel: RDV Dr. Laurent demain 14h30. Confirmer? Répondez OUI. Annuler? STOP" (79 chars)
  3. Delivery Notification: "Votre colis #MQ12345 arrive aujourd'hui 15h-18h. Suivre: lien.co/trk" (68 chars)
  4. Marketing (compliant): "ShopCaraïbe: -20% ce weekend ! Voir promos: bit.ly/promo20 STOP au 0696XX" (75 chars)

A/B Testing Framework:

typescript
interface ABTest {
  variant: 'A' | 'B';
  messageContent: string;
  sendTime: Date;
  recipientSegment: string[];
}

async function runABTest(testConfig: ABTest[]): Promise<ABTestResults> {
  const results = {
    variantA: { sent: 0, delivered: 0, clicked: 0, optedOut: 0 },
    variantB: { sent: 0, delivered: 0, clicked: 0, optedOut: 0 }
  };

  // Split recipients 50/50
  for (const test of testConfig) {
    const metrics = await sendAndTrack(test);
    results[`variant${test.variant}`] = metrics;
  }

  // Calculate performance
  return {
    winner: determineWinner(results),
    deliveryRate: calculateDeliveryRate(results),
    clickRate: calculateClickRate(results),
    optOutRate: calculateOptOutRate(results)
  };
}

Performance Benchmarks (Industry standards for Martinique):

  • Delivery rate: Target >98% (mobile operators), <95% indicates filtering
  • Read rate: 90-95% within 3 minutes for transactional SMS
  • Click-through rate: 8-12% for marketing SMS with strong CTA
  • Opt-out rate: <0.5% indicates good targeting; >2% suggests poor segmentation

Sending Frequency and Timing

  • Limit to 2-3 messages per week per recipient
  • Respect local holidays and cultural events (Carnival, Bastille Day, Christmas)
  • Avoid sending during off-hours (before 8 AM, after 10 PM AST)
  • Space out bulk campaigns (minimum 48 hours between marketing messages)

Engagement Optimization:

  • Best send times: Tuesday-Thursday, 10 AM-12 PM and 6 PM-8 PM AST (highest engagement)
  • Avoid: Monday mornings, Friday evenings, weekends (lower response rates)
  • Transactional SMS: Send immediately regardless of time (urgent notifications exempt from time restrictions)
  • Marketing campaigns: Schedule for mid-week mornings for optimal engagement

Localization

  • Primary language should be French (official language)
  • Consider including Creole for wider accessibility (spoken by ~90% of population)
  • Use local date and time formats (DD/MM/YYYY, 24-hour clock)
  • Respect cultural nuances and references (Carnival season, local holidays)

Creole Language Examples:

  • French: "Bonjour! Votre commande est prête. Merci!"
  • Creole: "Bonjou! Kòmand-ou la paré. Mèsi!"
  • French: "Nouveau message de votre médecin"
  • Creole: "Nouvo mesaj doktè-w"

Cultural Context:

  • Major events: Carnival (February/March), Bastille Day (July 14), All Saints' Day (November 1)
  • Avoid aggressive sales tactics; French Caribbean culture values relationship building
  • Use formal "vous" form for initial contact, "tu" for established customers
  • References to local landmarks (Fort-de-France, Mount Pelée) increase relevance

Translation Best Practices:

  • Use native French speakers for content review
  • Avoid machine translation for marketing messages
  • Consider professional translation services for legal/compliance content
  • Test messages with local focus groups before broad deployment

Opt-Out Management

  • Process opt-outs in real-time (immediate database update)
  • Maintain centralized opt-out database (synchronized across all systems)
  • Confirm opt-out status via SMS within 24 hours
  • Regular audit of opt-out lists (monthly reconciliation recommended)

Database Schema for Opt-Out Tracking:

sql
CREATE TABLE sms_opt_outs (
  id UUID PRIMARY KEY,
  phone_number VARCHAR(20) NOT NULL UNIQUE,
  opted_out_at TIMESTAMP NOT NULL DEFAULT NOW(),
  opt_out_source VARCHAR(50),  -- 'sms_reply', 'web_form', '33700_report'
  opt_out_reason VARCHAR(255),
  campaign_id UUID,
  permanent BOOLEAN DEFAULT true,
  confirmed BOOLEAN DEFAULT false,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  INDEX idx_phone (phone_number),
  INDEX idx_opted_out_at (opted_out_at)
);

-- Query before sending
SELECT COUNT(*) FROM sms_opt_outs
WHERE phone_number = '+596696123456'
AND permanent = true;

Testing and Monitoring

  • Test across major carriers (Orange, SFR, Digicel) before bulk sends
  • Monitor delivery rates by carrier (target >98%)
  • Track engagement metrics (delivery, read, click, opt-out rates)
  • Regular testing of opt-out functionality (monthly verification)

Key Metrics to Track:

  • Delivery rate by operator: Orange (target 99%), SFR (98%), Digicel (97%), Free (96%)
  • Time to delivery: <30 seconds for 95% of messages
  • Error rate by type: Invalid number (21614), network error (30003), spam filter (30007)
  • Opt-out rate trend: Monitor weekly; spike >1% indicates campaign issues

Troubleshooting Common Issues:

IssueLikely CauseResolution
Delivery rate <95%Spam filteringReview content for trigger words, test sender ID
High opt-out rate (>2%)Poor targetingAudit consent records, improve segmentation
Delivery delays >60sRate limitingImplement queue management, reduce send rate
Invalid number errorsOutdated databaseValidate numbers, implement HLR lookup
Carrier blockingSpam reports to 33700Contact carrier compliance team, audit content

SMS API integrations for Martinique (France)

Twilio

Twilio provides a robust SMS API for sending messages to Martinique. Authentication requires your Account SID and Auth Token. Pricing: $0.1401 per SMS (Twilio Pricing).

typescript
import { Twilio } from 'twilio';

// Initialize Twilio client
const client = new Twilio(
  process.env.TWILIO_ACCOUNT_SID,    // Your Account SID
  process.env.TWILIO_AUTH_TOKEN      // Your Auth Token
);

async function sendSMSToMartinique() {
  try {
    // Send message with proper formatting for Martinique numbers
    const message = await client.messages.create({
      body: 'Votre code de confirmation est: 123456',  // Message in French
      from: 'YourCompany',                            // Alphanumeric sender ID
      to: '+596696123456',                            // Martinique number format
      statusCallback: 'https://your-domain.com/sms/status'  // Delivery status webhook
    });

    console.log(`Message sent successfully: ${message.sid}`);
    return message.sid;
  } catch (error) {
    if (error.code === 21614) {
      console.error('Invalid phone number format');
    } else if (error.code === 30003) {
      console.error('Unreachable destination - carrier issue');
    } else if (error.code === 30007) {
      console.error('Message filtered as spam');
    } else {
      console.error('Error sending message:', error);
    }
    throw error;
  }
}

// Handle delivery status webhook
app.post('/sms/status', (req, res) => {
  const { MessageStatus, MessageSid, ErrorCode } = req.body;

  console.log(`Message ${MessageSid} status: ${MessageStatus}`);

  if (MessageStatus === 'failed' || MessageStatus === 'undelivered') {
    console.error(`Delivery failed with error code: ${ErrorCode}`);
    // Implement retry logic or alerting
  }

  res.sendStatus(200);
});

Sinch

Sinch offers SMS capabilities with RESTful API integration. Authentication uses your project ID and API token. Pricing: $0.1319 per SMS (lowest rate).

typescript
import { SinchClient } from '@sinch/sdk-core';

// Initialize Sinch client
const sinchClient = new SinchClient({
  projectId: 'YOUR_PROJECT_ID',
  apiToken: 'YOUR_API_TOKEN'
});

async function sendSMSViaSinch() {
  try {
    const response = await sinchClient.sms.batches.send({
      sendSMSRequestBody: {
        to: ['+596696123456'],
        from: 'YourBrand',
        body: 'Votre confirmation est requise.',
        delivery_report: 'summary'  // Request delivery report
      }
    });

    console.log('Message sent:', response.id);

    // Check delivery report
    const report = await sinchClient.sms.batches.get({
      batch_id: response.id
    });

    console.log(`Delivery status: ${report.delivery_report}`);
    return response.id;
  } catch (error) {
    console.error('Sinch API error:', error);
    throw error;
  }
}

// Delivery report interpretation
interface DeliveryReport {
  batch_id: string;
  statuses: {
    code: number;  // 0: delivered, 400: bad request, 403: forbidden, 404: not found
    status: string;  // 'Delivered', 'Failed', 'Expired'
    count: number;
  }[];
}

function interpretDeliveryReport(report: DeliveryReport): void {
  report.statuses.forEach(status => {
    switch (status.code) {
      case 0:
        console.log(`${status.count} messages delivered successfully`);
        break;
      case 400:
        console.error(`${status.count} messages failed: Invalid format`);
        break;
      case 403:
        console.error(`${status.count} messages rejected: Spam filter`);
        break;
      case 404:
        console.error(`${status.count} messages failed: Invalid number`);
        break;
      default:
        console.warn(`${status.count} messages status ${status.code}: ${status.status}`);
    }
  });
}

MessageBird

MessageBird provides SMS API access with straightforward integration. Uses API key authentication. Pricing: Contact for custom rates.

typescript
import { MessageBirdClient } from 'messagebird';

// Initialize MessageBird client
const messagebird = new MessageBirdClient('YOUR_API_KEY');

async function sendSMSViaMessageBird() {
  // Example: Schedule message for next available permitted time window
  const now = new Date();
  const scheduledTime = getNextAvailableSlot(now);  // From timezone example above

  const params = {
    originator: 'YourCompany',
    recipients: ['+596696123456'],
    body: 'Message important de notre service.',
    scheduledDatetime: scheduledTime.toISOString(),  // Schedule for permitted hours
  };

  try {
    const response = await messagebird.messages.create(params);
    console.log('Message scheduled:', response);
    return response.id;
  } catch (error) {
    console.error('MessageBird error:', error);
    throw error;
  }
}

Plivo

Plivo offers SMS capabilities with comprehensive delivery reporting. Authentication uses Auth ID and Auth Token. Pricing: $0.1359 per SMS.

typescript
import { Client } from 'plivo';
import express from 'express';

// Initialize Plivo client
const client = new Client(
  'YOUR_AUTH_ID',
  'YOUR_AUTH_TOKEN'
);

async function sendSMSViaPlivo() {
  try {
    const response = await client.messages.create({
      src: 'YourBrand',              // Sender ID
      dst: '+596696123456',          // Destination number
      text: 'Votre compte a été mis à jour.',
      url: 'https://your-callback-url.com/status'  // Status callback URL
    });

    console.log('Message sent with UUID:', response.messageUuid);
    return response.messageUuid;
  } catch (error) {
    console.error('Plivo error:', error);
    throw error;
  }
}

// Webhook handler for delivery status callbacks
const app = express();
app.use(express.urlencoded({ extended: true }));

app.post('/status', (req, res) => {
  const {
    MessageUUID,
    From,
    To,
    Status,
    ErrorCode,
    TotalRate,
    Units
  } = req.body;

  console.log(`Message ${MessageUUID} to ${To}: ${Status}`);

  // Status values: 'queued', 'sent', 'failed', 'delivered', 'undelivered', 'rejected'
  switch (Status) {
    case 'delivered':
      console.log(`Successfully delivered. Cost: $${TotalRate} (${Units} units)`);
      break;
    case 'failed':
    case 'undelivered':
      console.error(`Delivery failed. Error code: ${ErrorCode}`);
      // Common error codes:
      // - InvalidNumber: Invalid recipient number
      // - UnknownNumber: Number doesn't exist
      // - CarrierViolation: Content filtered by carrier
      break;
    case 'rejected':
      console.error(`Message rejected - likely spam filter`);
      break;
  }

  res.sendStatus(200);
});

app.listen(3000, () => console.log('Webhook server listening on port 3000'));

API Rate Limits and Throughput

Provider-Specific Rate Limits:

ProviderDefault Rate LimitBurst CapacityRecommended Throughput
Twilio10 msg/sec100 msg/burst5-8 msg/sec sustained
Plivo10 msg/sec50 msg/burst5-8 msg/sec sustained
Sinch20 msg/sec100 msg/burst10-15 msg/sec sustained
MessageBird5 msg/sec25 msg/burst3-4 msg/sec sustained

Notes: Rate limits apply per account. Enterprise accounts can negotiate higher limits. Martinique's permitted hours (8 AM-10 PM AST) should factor into throughput planning.

  • Implement exponential backoff for retry logic
  • Use batch APIs for bulk sending
  • Consider time window restrictions when scheduling messages

Throughput Management Strategies:

typescript
// Production-ready rate limiter with retry logic
class RateLimiter {
  private queue: Array<() => Promise<void>> = [];
  private processing = false;
  private rateLimit = 5; // Messages per second (conservative for Martinique)
  private retryAttempts = 3;
  private backoffMultiplier = 2;

  async add(task: () => Promise<void>, priority: 'high' | 'normal' = 'normal') {
    if (priority === 'high') {
      this.queue.unshift(task);  // High priority to front
    } else {
      this.queue.push(task);
    }

    if (!this.processing) {
      this.process();
    }
  }

  private async process() {
    this.processing = true;

    while (this.queue.length > 0) {
      // Check if within permitted time window
      if (!canSendSMS(new Date())) {
        const nextSlot = getNextAvailableSlot(new Date());
        const waitTime = nextSlot.getTime() - Date.now();
        console.log(`Outside permitted hours. Waiting ${waitTime / 1000}s`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
      }

      const task = this.queue.shift();
      if (task) {
        await this.executeWithRetry(task);
        await new Promise(resolve => setTimeout(resolve, 1000 / this.rateLimit));
      }
    }

    this.processing = false;
  }

  private async executeWithRetry(task: () => Promise<void>, attempt = 1): Promise<void> {
    try {
      await task();
    } catch (error) {
      if (attempt < this.retryAttempts) {
        const backoff = Math.pow(this.backoffMultiplier, attempt) * 1000;
        console.log(`Retry attempt ${attempt} after ${backoff}ms`);
        await new Promise(resolve => setTimeout(resolve, backoff));
        return this.executeWithRetry(task, attempt + 1);
      }
      throw error;
    }
  }
}

// Usage
const limiter = new RateLimiter();
for (const recipient of recipients) {
  limiter.add(async () => {
    await sendSMS(recipient);
  }, recipient.isUrgent ? 'high' : 'normal');
}

Error Handling and Reporting

typescript
// Example error handling implementation
interface SMSError {
  code: string;
  message: string;
  timestamp: Date;
  recipient: string;
  provider: string;
  retryable: boolean;
}

class SMSErrorHandler {
  private errors: SMSError[] = [];
  private alertThreshold = 10;  // Alert if >10 errors in 5 minutes

  logError(error: SMSError) {
    this.errors.push(error);
    console.error(`SMS Error ${error.code}: ${error.message}`);

    // Implement specific handling based on error code
    switch(error.code) {
      case '21614': // Invalid number
        this.handleInvalidNumber(error);
        break;
      case '30003': // Queue full
        this.handleQueueFull(error);
        break;
      case '30007': // Spam filter
        this.handleSpamFilter(error);
        break;
      default:
        this.handleGenericError(error);
    }

    // Check if alert threshold reached
    this.checkAlertThreshold();
  }

  private handleInvalidNumber(error: SMSError) {
    // Remove from database or flag for review
    console.log(`Marking ${error.recipient} as invalid`);
    // database.markInvalid(error.recipient);
  }

  private handleQueueFull(error: SMSError) {
    // Retry with exponential backoff
    if (error.retryable) {
      console.log(`Queueing ${error.recipient} for retry`);
      // retryQueue.add(error.recipient);
    }
  }

  private handleSpamFilter(error: SMSError) {
    // Alert content team to review message content
    console.error(`SPAM FILTER: Message to ${error.recipient} blocked`);
    // sendAlert('Content review needed - spam filter triggered');
  }

  private handleGenericError(error: SMSError) {
    // Log for monitoring and escalate if persistent
    console.error(`Generic error for ${error.recipient}: ${error.message}`);
  }

  private checkAlertThreshold() {
    const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
    const recentErrors = this.errors.filter(e => e.timestamp > fiveMinutesAgo);

    if (recentErrors.length >= this.alertThreshold) {
      this.sendAlert(`High error rate: ${recentErrors.length} errors in 5 minutes`);
    }
  }

  private sendAlert(message: string) {
    // Integrate with monitoring service (PagerDuty, Datadog, etc.)
    console.error(`ALERT: ${message}`);
    // monitoring.alert({ severity: 'high', message });
  }

  getErrorReport(since: Date): { [key: string]: number } {
    return this.errors
      .filter(e => e.timestamp > since)
      .reduce((acc, error) => {
        acc[error.code] = (acc[error.code] || 0) + 1;
        return acc;
      }, {} as { [key: string]: number });
  }
}

// Integration with logging service
import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'sms-combined.log' })
  ]
});

function logSMSMetrics(metrics: { sent: number; delivered: number; failed: number }) {
  logger.info('SMS Metrics', {
    timestamp: new Date(),
    ...metrics,
    deliveryRate: (metrics.delivered / metrics.sent * 100).toFixed(2) + '%'
  });
}

Frequently Asked Questions

What is the phone number format for Martinique SMS?

Martinique uses a 10-digit numbering system with +596 country code. Mobile numbers use prefixes 0696 or 0697 (national format) or +596 696/697 (international E.164 format). Example: +596696123456. Landlines use 0596 prefix but cannot receive SMS messages.

Yes. Article L34-5 of the French CPCE requires explicit written consent before sending marketing SMS to consumers (B2C). Consent must be freely given, specific, informed, and unambiguous. Exception: Existing customers receiving offers for similar products/services require only opt-out consent.

Does Bloctel registry apply to SMS in Martinique?

No. Bloctel is France's do-not-call registry for voice calls ONLY and does NOT cover SMS or MMS messages. For SMS opt-outs, use the STOP SMS system, CONTACT command, or 33700 reporting service instead.

Which mobile operators serve Martinique?

Four major operators serve Martinique: Orange Caraïbe (#1 network according to July 2024 ARCEP survey), SFR Caraïbe, Digicel, and Free Caraïbe. Outremer Telecom (La Poste Mobile Caraïbe) also operates in the market. 5G became available February 18, 2025.

Is number portability available in Martinique?

Yes. Mobile Number Portability (MNP) launched in 2006 and follows a 10-day porting process regulated by ARCEP. Customers can switch operators while keeping their phone numbers, so prefix-based carrier identification is unreliable.

What are the permitted hours for sending SMS in Martinique?

Send marketing SMS only between 8:00 AM and 10:00 PM Atlantic Standard Time (AST, UTC-4). Avoid Sundays and public holidays. Emergency and transactional messages are exempt from time restrictions. Martinique does not observe daylight saving time.

What are the penalties for SMS marketing violations in Martinique?

Under 2024 French legislation (effective January 2026), maximum fines reach €500,000 or up to 20% of annual turnover. CNIL imposed a €525,000 fine on HUBSIDE.STORE in 2024 for consent violations. In 2024, CNIL issued 87 sanctions totaling €55.2 million, with commercial prospecting violations as a priority enforcement area. Criminal penalties apply for grave offenses.

Does Martinique support two-way SMS?

No. Two-way SMS is not supported in Martinique through major SMS providers. Design your messaging strategies around one-way communications only. Concatenated messages are also not supported due to carrier infrastructure limitations.

How much does it cost to send SMS in Martinique?

International API providers charge $0.1319–$0.1401 per SMS: Sinch ($0.1319, lowest), Plivo ($0.1359), Twilio ($0.1401). High-volume senders (10,000+ messages/month) can negotiate 15–30% discounts. Actual costs vary by volume, provider, and contractual terms (source).

What are common technical issues when sending SMS to Martinique?

Common issues include: (1) Invalid number format errors (code 21614) - ensure +596696/697 format; (2) Spam filtering (code 30007) - avoid trigger words and excessive punctuation; (3) Delivery delays - implement rate limiting and respect carrier throttling; (4) High opt-out rates - audit consent records and improve targeting; (5) Number portability - use HLR lookup instead of prefix-based routing.

Recap and Additional Resources

Key Takeaways

Pre-Launch Checklist:

  • Obtain explicit opt-in consent with documented timestamp, source, and scope
  • Implement STOP/ARRETER/DESABONNEMENT keyword processing
  • Configure timezone restrictions (8 AM-10 PM AST, no Sundays/holidays)
  • Validate all numbers against +596696/697 pattern
  • Set up delivery rate monitoring (target >98%)
  • Test messages across Orange, SFR, and Digicel networks
  • Prepare 33700 spam service integration
  • Configure opt-out database and real-time processing
  • Establish rate limiting (5-10 msg/sec maximum)
  • Review content for compliance (no gambling, crypto, adult content)

Critical Compliance Points:

  1. Consent First: Always obtain explicit consent per Article L34-5 CPCE before sending marketing messages
  2. Timing Matters: Respect 8 AM-10 PM AST window; no Sundays or public holidays
  3. Language Requirements: Use French as primary; consider Creole for accessibility
  4. Technical Implementation: Implement proper error handling, rate limiting, and delivery monitoring
  5. Documentation: Maintain consent records for minimum 3 years
  6. Prepare for 2026: New penalties (€500,000 or 20% turnover) effective January 2026

Next Steps

Implementation Timeline (Estimated 6-8 weeks):

  1. Week 1-2: Review ARCEP and CNIL regulations; audit existing consent database
  2. Week 3-4: Implement consent collection mechanisms with proper documentation
  3. Week 5-6: Set up monitoring, rate limiting, and error handling systems
  4. Week 7-8: Test thoroughly across all major carriers; launch pilot campaign

Resource Requirements:

  • Development: 40-60 hours for API integration, consent management, monitoring dashboards
  • Legal Review: 8-16 hours for compliance audit and policy documentation
  • Testing: 16-24 hours for multi-carrier testing and optimization
  • Budget: $500-2,000 for initial setup (API accounts, monitoring tools, test credits)

Additional Resources