Sync your CRM
Your CRM stays the source of truth. Noticia mirrors the customers you want to activate and records their SMS consent. This guide shows the two-call pattern: upsert the profile, then opt the customer in.
1. Upsert the profile
Section titled “1. Upsert the profile”Push each customer as a profile keyed on your own externalId. The call is an upsert: safe to repeat, never creates a duplicate. Send it on customer creation and on every change you want reflected (last write wins).
curl https://api.sms.noticia.ai/v1/profiles \ -X POST \ -H "x-api-key: ntca_REPLACE_ME" \ -H "Content-Type: application/json" \ -d '{ "externalId": "crm-customer-4815", "phoneNumber": "+33612345678", "firstName": "Camille", "lastName": "Durand", "attributes": { "tier": "gold", "favorite_store": "lyon-part-dieu" } }'await fetch('https://api.sms.noticia.ai/v1/profiles', { method: 'POST', headers: { 'x-api-key': 'ntca_REPLACE_ME', 'Content-Type': 'application/json', }, body: JSON.stringify({ externalId: 'crm-customer-4815', phoneNumber: '+33612345678', firstName: 'Camille', lastName: 'Durand', attributes: { tier: 'gold', favorite_store: 'lyon-part-dieu' }, }),});import requests
requests.post( "https://api.sms.noticia.ai/v1/profiles", headers={"x-api-key": "ntca_REPLACE_ME"}, json={ "externalId": "crm-customer-4815", "phoneNumber": "+33612345678", "firstName": "Camille", "lastName": "Durand", "attributes": {"tier": "gold", "favorite_store": "lyon-part-dieu"}, },)2. Capture consent
Section titled “2. Capture consent”A profile with a phone number is not allowed to receive SMS. You must record an explicit opt-in. Reference the same customer with profileId and capture where consent came from.
curl https://api.sms.noticia.ai/v1/subscriptions/opt-in \ -X POST \ -H "x-api-key: ntca_REPLACE_ME" \ -H "Content-Type: application/json" \ -d '{ "phoneNumber": "+33612345678", "profileId": "crm-customer-4815", "consentSource": "LOYALTY_PROGRAM", "consentedAt": "2026-05-28T10:00:00.000Z", "consentProof": { "termsUrl": "https://brand.example/sms-terms", "termsVersion": "v2.3", "sourceText": "Loyalty signup, Lyon Part-Dieu" } }'await fetch('https://api.sms.noticia.ai/v1/subscriptions/opt-in', { method: 'POST', headers: { 'x-api-key': 'ntca_REPLACE_ME', 'Content-Type': 'application/json', }, body: JSON.stringify({ phoneNumber: '+33612345678', profileId: 'crm-customer-4815', consentSource: 'LOYALTY_PROGRAM', consentedAt: '2026-05-28T10:00:00.000Z', consentProof: { termsUrl: 'https://brand.example/sms-terms', termsVersion: 'v2.3', sourceText: 'Loyalty signup, Lyon Part-Dieu', }, }),});import requests
requests.post( "https://api.sms.noticia.ai/v1/subscriptions/opt-in", headers={"x-api-key": "ntca_REPLACE_ME"}, json={ "phoneNumber": "+33612345678", "profileId": "crm-customer-4815", "consentSource": "LOYALTY_PROGRAM", "consentedAt": "2026-05-28T10:00:00.000Z", "consentProof": { "termsUrl": "https://brand.example/sms-terms", "termsVersion": "v2.3", "sourceText": "Loyalty signup, Lyon Part-Dieu", }, },)The response is the resulting subscription with status: "SUBSCRIBED". From now on the customer is reachable by Noticia segments, journeys and campaigns.
{ "phoneNumber": "+33612345678", "status": "SUBSCRIBED", "consentSource": "LOYALTY_PROGRAM", "consentedAt": "2026-05-28T10:00:00.000Z", "unsubscribedAt": null, "profile": { "id": "prof_cl9z3k1xb0000v8x9d2a1b3c4", "externalId": "crm-customer-4815" }}Keeping in sync
Section titled “Keeping in sync”- New customer: upsert the profile, then opt in if they consented.
- Updated customer: upsert the profile again. Last write wins.
- Withdrawn consent: call
POST /v1/subscriptions/opt-out. ASTOPreply does this automatically.
You do not need a full two-way sync. Push what drives activation, keep your CRM authoritative, and let opt-outs flow back through webhooks when that ships.
Reliability
Section titled “Reliability”Wrap each write with an Idempotency-Key so a network retry never creates a duplicate, and handle errors with the recommended back-off.