requirements.json
1 { 2 "_comment": "Country+channel compliance requirements. Booleans unless noted. 'warn' = log warning only, do not block. optOutSpintax is appended to SMS templates at generation time by create-locale-templates.js. optOutFallback is used by sms.js safety net at send time (US/CA only).", 3 "_flags": { 4 "requiresPhysicalAddress": "Email must include sender's street address in footer (CAN-SPAM / Spam Act)", 5 "requiresUnsubscribeLink": "Email must include functional unsubscribe link", 6 "requiresOptOutInBody": "SMS body must contain opt-out instructions. Twilio processes STOP case-insensitively. Use lowercase 'stop' for optional markets (less spammy); keep 'STOP' uppercase for US/CA where CTIA Best Practices explicitly recommend the visible keyword.", 7 "requiresSenderIdInBody": "SMS body must identify the sender by name/company", 8 "requiresBusinessHours": "SMS only sent 8am-9pm recipient's local time", 9 "requiresExpressConsent": "Prior written consent required — 'warn' because we send informational-only cold outreach", 10 "requiresGdprVerification": "Company email must be verified before sending (EU/GDPR countries)", 11 "requiresImpressum": "German legal disclosure (Impressum) required — 'warn' only, complex to automate", 12 "optOutSpintax": "Spintax appended to SMS body_spintax by create-locale-templates.js at generation time. STOP/stop must appear in Latin characters (Twilio keyword). Non-English countries: keep STOP in caps (recognisable loan word).", 13 "optOutFallback": "Plain text appended by sms.js safety net if STOP absent from body at send time (US/CA/KR only)" 14 }, 15 "AU": { 16 "email": { 17 "requiresPhysicalAddress": true, 18 "requiresUnsubscribeLink": true 19 }, 20 "sms": { 21 "requiresOptOutInBody": false, 22 "requiresSenderIdInBody": false, 23 "requiresBusinessHours": false, 24 "optOutSpintax": "{Not interested? Just reply 'stop'.|Happy to remove you — just text STOP.|No problem — text 'stop' to unsubscribe.|Rather not hear from me? Just reply STOP.}" 25 } 26 }, 27 "NZ": { 28 "email": { 29 "requiresPhysicalAddress": true, 30 "requiresUnsubscribeLink": true 31 }, 32 "sms": { 33 "requiresOptOutInBody": false, 34 "requiresSenderIdInBody": false, 35 "requiresBusinessHours": false, 36 "optOutSpintax": "{Not for you? Just reply 'stop'.|No worries — just text STOP.|Want out? Reply 'stop' anytime.|Rather not? Just text STOP.}" 37 } 38 }, 39 "GB": { 40 "email": { 41 "requiresPhysicalAddress": true, 42 "requiresUnsubscribeLink": true 43 }, 44 "sms": { 45 "requiresOptOutInBody": false, 46 "requiresSenderIdInBody": false, 47 "requiresBusinessHours": false, 48 "optOutSpintax": "{Not for you? Text 'stop' anytime.|Reply STOP if you'd rather not hear from us.|No problem — just reply 'stop'.|Prefer not to receive these? Text STOP.}" 49 } 50 }, 51 "IE": { 52 "email": { 53 "requiresPhysicalAddress": true, 54 "requiresUnsubscribeLink": true 55 }, 56 "sms": { 57 "requiresOptOutInBody": false, 58 "requiresSenderIdInBody": false, 59 "requiresBusinessHours": false, 60 "optOutSpintax": "{Not for you? Text 'stop' anytime.|Reply STOP if you'd rather not hear from us.|No bother — just reply 'stop'.|Prefer not to receive these? Text STOP.}" 61 } 62 }, 63 "CA": { 64 "email": { 65 "requiresPhysicalAddress": true, 66 "requiresUnsubscribeLink": true 67 }, 68 "sms": { 69 "requiresOptOutInBody": true, 70 "requiresSenderIdInBody": true, 71 "requiresBusinessHours": true, 72 "requiresExpressConsent": "warn", 73 "optOutSpintax": "{Reply STOP to opt out.|Text STOP anytime to unsubscribe.|Want to stop? Reply STOP.|No longer interested? Reply STOP.}", 74 "optOutFallback": "Reply STOP to opt out." 75 } 76 }, 77 "US": { 78 "email": { 79 "requiresPhysicalAddress": true, 80 "requiresUnsubscribeLink": true 81 }, 82 "sms": { 83 "requiresOptOutInBody": true, 84 "requiresSenderIdInBody": true, 85 "requiresBusinessHours": true, 86 "requiresExpressConsent": "warn", 87 "optOutSpintax": "{Reply STOP to opt out.|Text STOP anytime to unsubscribe.|Want to stop? Reply STOP.|No longer interested? Reply STOP.}", 88 "optOutFallback": "Reply STOP to opt out." 89 } 90 }, 91 "IN": { 92 "email": { 93 "requiresPhysicalAddress": false, 94 "requiresUnsubscribeLink": true 95 }, 96 "sms": { 97 "requiresOptOutInBody": false, 98 "requiresSenderIdInBody": false, 99 "requiresBusinessHours": false, 100 "optOutSpintax": "{Not interested? Reply 'stop'.|No worries — just text STOP.|Want to opt out? Reply 'stop'.|Happy to remove you — just reply STOP.}" 101 } 102 }, 103 "JP": { 104 "_comment": "Japan Anti-Spam Act is consent-centric — no opt-out text required in message body. Processing STOP/opt-out replies is required at campaign level. STOP processed by Twilio globally.", 105 "email": { 106 "requiresPhysicalAddress": true, 107 "requiresUnsubscribeLink": true 108 }, 109 "sms": { 110 "requiresOptOutInBody": false, 111 "requiresSenderIdInBody": false, 112 "requiresBusinessHours": false, 113 "optOutSpintax": "{ご不要の場合は STOP とご返信ください。|配信停止は STOP とご返信ください。|不要な方は STOP とご返信いただければ停止します。|ご興味なければ STOP とご返信ください。}" 114 } 115 }, 116 "KR": { 117 "_comment": "Korean Network Act (정보통신망법) mandates opt-out instructions in every promotional SMS. '수신거부' is the standard Korean keyword; STOP also processed by Twilio. No optOutFallback — Korean opt-out must be in Korean.", 118 "email": { 119 "requiresPhysicalAddress": true, 120 "requiresUnsubscribeLink": true 121 }, 122 "sms": { 123 "requiresOptOutInBody": true, 124 "requiresSenderIdInBody": false, 125 "requiresBusinessHours": false, 126 "optOutSpintax": "{원치 않으시면 STOP 으로 답장하세요.|수신 거부하려면 STOP 으로 답장하세요.|더 이상 받고 싶지 않으시면 STOP 으로 답장해 주세요.|수신 취소: STOP 으로 답장하세요.}", 127 "optOutFallback": "수신 거부: STOP 으로 답장하세요." 128 } 129 }, 130 "DE": { 131 "email": { 132 "requiresPhysicalAddress": true, 133 "requiresUnsubscribeLink": true, 134 "requiresGdprVerification": true, 135 "requiresImpressum": "warn" 136 }, 137 "sms": { 138 "requiresOptOutInBody": false, 139 "requiresSenderIdInBody": false, 140 "requiresBusinessHours": false, 141 "optOutSpintax": "{Kein Interesse? Antworten Sie mit STOP.|Abmelden: einfach STOP antworten.|Nicht mehr interessiert? Einfach STOP zurückschreiben.|Kein Problem — antworte einfach STOP.}" 142 } 143 }, 144 "FR": { 145 "email": { 146 "requiresPhysicalAddress": true, 147 "requiresUnsubscribeLink": true, 148 "requiresGdprVerification": true 149 }, 150 "sms": { 151 "requiresOptOutInBody": false, 152 "requiresSenderIdInBody": false, 153 "requiresBusinessHours": false, 154 "optOutSpintax": "{Pas intéressé ? Répondez STOP.|Pour vous désabonner, répondez STOP.|Pas de problème — répondez simplement STOP.|Plus intéressé ? Un STOP suffit.}" 155 } 156 }, 157 "IT": { 158 "email": { 159 "requiresPhysicalAddress": true, 160 "requiresUnsubscribeLink": true, 161 "requiresGdprVerification": true 162 }, 163 "sms": { 164 "requiresOptOutInBody": false, 165 "requiresSenderIdInBody": false, 166 "requiresBusinessHours": false, 167 "optOutSpintax": "{Non interessato? Rispondi STOP.|Per cancellare l'iscrizione, rispondi STOP.|Nessun problema — rispondi STOP per disiscriverti.|Non vuoi più ricevermi? Rispondi STOP.}" 168 } 169 }, 170 "ES": { 171 "email": { 172 "requiresPhysicalAddress": true, 173 "requiresUnsubscribeLink": true, 174 "requiresGdprVerification": true 175 }, 176 "sms": { 177 "requiresOptOutInBody": false, 178 "requiresSenderIdInBody": false, 179 "requiresBusinessHours": false, 180 "optOutSpintax": "{¿No te interesa? Responde STOP.|Para cancelar, responde STOP.|Sin problema — responde STOP cuando quieras.|¿Ya no te interesa? Basta con responder STOP.}" 181 } 182 }, 183 "MX": { 184 "email": { 185 "requiresPhysicalAddress": false, 186 "requiresUnsubscribeLink": true 187 }, 188 "sms": { 189 "requiresOptOutInBody": false, 190 "requiresSenderIdInBody": false, 191 "requiresBusinessHours": false, 192 "optOutSpintax": "{¿No te interesa? Responde STOP.|Para cancelar, responde STOP.|Sin problema — responde STOP cuando quieras.|¿Ya no te interesa? Basta con responder STOP.}" 193 } 194 }, 195 "NL": { 196 "email": { 197 "requiresPhysicalAddress": true, 198 "requiresUnsubscribeLink": true, 199 "requiresGdprVerification": true 200 }, 201 "sms": { 202 "requiresOptOutInBody": false, 203 "requiresSenderIdInBody": false, 204 "requiresBusinessHours": false, 205 "optOutSpintax": "{Geen interesse? Stuur STOP terug.|Afmelden: antwoord STOP.|Liever niet meer ontvangen? Antwoord STOP.|Geen probleem — stuur gewoon STOP terug.}" 206 } 207 }, 208 "SE": { 209 "email": { 210 "requiresPhysicalAddress": true, 211 "requiresUnsubscribeLink": true, 212 "requiresGdprVerification": true 213 }, 214 "sms": { 215 "requiresOptOutInBody": false, 216 "requiresSenderIdInBody": false, 217 "requiresBusinessHours": false, 218 "optOutSpintax": "{Inte intresserad? Svara STOP.|Avregistrera dig: svara STOP.|Inga problem — svara bara STOP.|Vill du sluta ta emot? Svara STOP.}" 219 } 220 }, 221 "DK": { 222 "email": { 223 "requiresPhysicalAddress": true, 224 "requiresUnsubscribeLink": true, 225 "requiresGdprVerification": true 226 }, 227 "sms": { 228 "requiresOptOutInBody": false, 229 "requiresSenderIdInBody": false, 230 "requiresBusinessHours": false, 231 "optOutSpintax": "{Ikke interesseret? Svar STOP.|Afmeld: svar STOP.|Intet problem — svar bare STOP.|Vil du afmelde dig? Svar STOP.}" 232 } 233 }, 234 "PL": { 235 "email": { 236 "requiresPhysicalAddress": true, 237 "requiresUnsubscribeLink": true, 238 "requiresGdprVerification": true 239 }, 240 "sms": { 241 "requiresOptOutInBody": false, 242 "requiresSenderIdInBody": false, 243 "requiresBusinessHours": false, 244 "optOutSpintax": "{Nie jesteś zainteresowany? Odpowiedz STOP.|Aby zrezygnować, odpowiedz STOP.|Bez problemu — wystarczy odpowiedzieć STOP.|Chcesz zrezygnować? Odpowiedz STOP.}" 245 } 246 }, 247 "ID": { 248 "email": { 249 "requiresPhysicalAddress": false, 250 "requiresUnsubscribeLink": true 251 }, 252 "sms": { 253 "requiresOptOutInBody": false, 254 "requiresSenderIdInBody": false, 255 "requiresBusinessHours": false, 256 "optOutSpintax": "{Tidak tertarik? Balas STOP.|Untuk berhenti, balas STOP.|Tidak masalah — cukup balas STOP.|Ingin berhenti menerima pesan? Balas STOP.}" 257 } 258 }, 259 "ZA": { 260 "email": { 261 "requiresPhysicalAddress": true, 262 "requiresUnsubscribeLink": true 263 }, 264 "sms": { 265 "requiresOptOutInBody": false, 266 "requiresSenderIdInBody": false, 267 "requiresBusinessHours": false, 268 "optOutSpintax": "{Not interested? Just reply 'stop'.|Happy to remove you — just text STOP.|No problem — text 'stop' to unsubscribe.|Rather not hear from me? Just reply STOP.}" 269 } 270 } 271 }