Att bygga kundresor med rik media, karuseller och interaktiva knappar i RCS ger högre engagemang än någonsin. Men i en verklighet där mobildatatäckningen tillfälligt kan svika, nätverkstimeouts kan uppstå eller mottagarens enhet saknar RCS-stöd, ställs höga krav på leveranssäkerheten. Lösningen är en intelligent SMS-fallback-logik – inbyggd direkt i API-infrastrukturen.
Med en genomtänkt fallback-strategi behöver du aldrig välja mellan rik interaktivitet och 100 % räckvidd. Om ett RCS-meddelande inte kan levereras, kopplar systemet sömlöst om till SMS via exakt samma API-endpoint utan att du behöver bygga egna komplexa redundanssystem.
Varför krävs en automatiserad fallback-logik?
Även om utrullningen av RCS går snabbt över hela världen, finns det situationer där ett databaserat meddelande inte når hela vägen fram till mottagarens skärm:
- Tillfällig avsaknad av mobildata: Mottagaren befinner sig i en skugga med svag mobildatadäckning (t.ex. på ett tåg, i ett garage eller utomlands utan roaming). Där når klassisk SMS-signalering fortfarande fram, men mobildatakopplingen ligger nere.
- Saknat RCS-stöd hos mottagaren: Vid de fall mottagarens enhet, operatör eller applikation ännu inte stödjer RCS.
- Nätverkstimeouts och operatörsfördröjningar: Om operatörens RCS-gateway inte bekräftar leveransen inom angiven tidsram måste meddelandet säkras via reservkanalen.
Genom att låta API:et automatiskt övervaka leveranskedjan garanteras att affärskritiska meddelanden som engångskoder (OTP), leveransuppdateringar eller tidskritiska erbjudanden, alltid når kunden.
De fem fallback-policyerna
I API:et styrs reservlogiken via parametern fallbackPolicy. Du kan välja en enskild policy eller kombinationer av dem i en kommaseparerad sträng för att skräddarsy beteendet efter meddelandets karaktär.
| Policy | Beskrivning | Typiskt användningsområde |
|---|---|---|
| NoFallback | Ingen fallback utförs. Om RCS misslyckas avbryts leveransen. | Ickekritiska rika meddelanden som saknar SMS-motsvarighet. |
| FallbackOnNoCapability | SMS skickas om mottagaren saknar stöd för RCS. | Grundläggande räckviddssäkring inför utskick. |
| FallbackOnFailure | SMS skickas om RCS-meddelandet avvisas eller misslyckas i nätverket. | Skydd mot tekniska nätverksfel eller fel hos operatör. |
| FallbackAfterTimeout | SMS skickas om leveransbekräftelse inte mottagits inom en viss tid. | Tidskritiska meddelanden (t.ex. inloggningskoder). |
| CustomerControlledFallback | Systemet skickar callbacks så att din applikation själv kan styra fallback-stegen externt. | Komplexa affärssystem med egna affärsregler. |
Pro-tip: Kombinera flera policyer för maximal trygghet, till exempel:
"fallbackPolicy": "FallbackOnNoCapability,FallbackOnFailure,FallbackAfterTimeout"
Konfiguration av reservmeddelandet (fallbackMessage)
Ett RCS-meddelande kan innehålla en produktkarusell, högupplösta bilder och interaktiva knappar. Eftersom SMS är ett rent textformat är det Best Practice att definiera ett dedikerat fallbackMessage.
Om inget fallbackMessage anges försöker systemet autogenerera text från RCS-innehållet, men genom att sätta en explicit text säkerställer du att budskapet framgår tydligt även i SMS-form:
- RCS (Rich Card): Bild på paket + interaktiv ”Spåra leverans”-knapp.
- SMS (fallbackMessage): ”Ditt paket är på väg! Spåra din leverans här: https://dinhemsida.se/spara/12345”
För tidskritiska utskick aktiverar du även fallbackTimeOutSeconds, som anger hur många sekunder plattformen väntar på att RCS-leveransen bekräftas innan SMS-reserven aktiveras.
API-implementation med kodexempel
Alla anrop görs mot plattformens bas-URL med autentisering via Bearer Token.
Exempel 1: Enskild mottagare (POST /v3/conversations)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var apiKey = "DIN_API_NYCKEL";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
var payload = new
{
brand: "mitt-varumarke",
agent: "kundtjanst",
recipient: "46700123456",
fallbackPolicy: "FallbackOnNoCapability,FallbackOnFailure,FallbackAfterTimeout",
fallbackMessage: "Hej! Din servicetid är bokad till 15 juni kl 10:00. Vill du omboka? https://dinhemsida.se/omboka/12345",
fallbackTimeOutSeconds: 300,
type: "Card",
card: {
title: "Bokningsbekräftelse",
content: "Välkommen på service den 15 juni kl 10:00.",
mediaUrl: "https://cdn.dinhemsida.se/bilder/service.png",
type: "Standalone",
order: 0,
height: "Medium",
orientation: "Horizontal",
suggestions: [
{
text: "Omboka tid",
type: "OpenUrlAction",
order: 1,
url: "https://dinhemsida.se/omboka/12345",
postbackData: "reschedule_12345",
}
]
},
};
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.ip1.net/v3/conversations", content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status: {response.StatusCode}\nSvar: {result}");
import asyncio
import httpx
api_key = "DIN_API_NYCKEL"
url = "https://api.ip1.net/v3/conversations"
payload = {
"brand": "mitt-varumarke",
"agent": "kundtjanst",
"recipient": "46700123456",
"fallbackPolicy": "FallbackOnNoCapability,FallbackOnFailure,FallbackAfterTimeout",
"fallbackMessage": "Hej! Din servicetid är bokad till 15 juni kl 10:00. Vill du omboka? https://dinhemsida.se/omboka/12345",
"fallbackTimeOutSeconds": 300,
"type": "Card",
"card": {
"title": "Bokningsbekräftelse",
"content": "Välkommen på service den 15 juni kl 10:00.",
"mediaUrl": "https://cdn.dinhemsida.se/bilder/service.png",
"type": "Standalone",
"order": 0,
"height": "Medium",
"orientation": "Horizontal",
"suggestions": [
{
"text": "Omboka tid",
"type": "OpenUrlAction",
"order": 1,
"url": "https://dinhemsida.se/omboka/12345",
"postbackData": "reschedule_12345"
}
]
}
}
async def send_message():
headers = {"Authorization": f"Bearer {api_key}"}
async with httpx.AsyncClient(headers=headers) as client:
response = await client.post(url, json=payload)
print(f"Status: {response.status_code}\nSvar: {response.text}")
asyncio.run(send_message())
const apiKey = "DIN_API_NYCKEL";
const url = "https://api.ip1.net/v3/conversations";
const payload: ConversationPayload = {
brand: "mitt-varumarke",
agent: "kundtjanst",
recipient: "46700123456",
fallbackPolicy: "FallbackOnNoCapability,FallbackOnFailure,FallbackAfterTimeout",
fallbackMessage: "Hej! Din servicetid är bokad till 15 juni kl 10:00. Vill du omboka? https://dinhemsida.se/omboka/12345",
fallbackTimeOutSeconds: 300,
type: "Card",
card: {
title: "Bokningsbekräftelse",
content: "Välkommen på service den 15 juni kl 10:00.",
mediaUrl: "https://cdn.dinhemsida.se/bilder/service.png",
type: "Standalone",
order: 0,
height: "Medium",
orientation: "Horizontal",
suggestions: [
{
text: "Omboka tid",
type: "OpenUrlAction",
order: 1,
url: "https://dinhemsida.se/omboka/12345",
postbackData: "reschedule_12345",
},
],
},
};
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const result = await response.text();
console.log(`Status: ${response.status}\nSvar: ${result}`);
Exempel 2: Flera mottagare / Massutskick (POST /v3/bundles)
using System.Net.Http.Json;
var apiKey = "DIN_API_NYCKEL";
var rcsUrl = "https://api.ip1.net/v3";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
async Task SendSmartMessages(string[] recipients, string text)
{
var rcsResponse = await client.PostAsJsonAsync($"{rcsUrl}/bundles", new
{
brand = "min-butik-ab",
agent = "DIN_AGENTS_ID",
type = "Card",
card = new
{
title = "Höstkampanj 2026",
content = "Få 20% rabatt på alla varor i vår butik under hela oktober månad. Besök oss idag!",
mediaUrl = "https://example.com/images/hoestkampanj.jpg",
type = "Standalone",
order = 0,
suggestions = new[]
{
new
{
label = "Besök vår butik",
order = 0,
type = "OpenUrlAction",
url = "https://example.com/butik"
},
new
{
label = "Se fler erbjudanden",
order = 1,
type = "OpenUrlAction",
url = "https://example.com/erbjudanden"
}
},
height = "Medium",
Orientation = "Vertical"
},
recipients = recipients,
fallbackPolicy = "FallbackOnNoCapability, FallbackOnFailure",
fallbackMessage = text
});
}
var myNumbers = new[] { "46700123456", "46700987654", "456189040623" };
await SendSmartMessages(myNumbers, "Hej! Detta är ett smart meddelande.");
import requests
API_KEY = "DIN_API_NYCKEL"
RCS_URL = "https://api.ip1.net/v3"
session = requests.Session()
session.headers.update({
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
})
def send_smart_messages(recipients: list[str], text: str):
payload = {
"brand": "min-butik-ab",
"agent": "DIN_AGENTS_ID",
"type": "Card",
"card": {
"title": "Höstkampanj 2026",
"content": "Få 20% rabatt på alla varor i vår butik under hela oktober månad. Besök oss idag!",
"mediaUrl": "https://example.com/images/hoestkampanj.jpg",
"type": "Standalone",
"order": 0,
"suggestions": [
{
"label": "Besök vår butik",
"order": 0,
"type": "OpenUrlAction",
"url": "https://example.com/butik"
},
{
"label": "Se fler erbjudanden",
"order": 1,
"type": "OpenUrlAction",
"url": "https://example.com/erbjudanden"
}
],
"height": "Medium",
"Orientation": "Vertical"
},
"recipients": recipients,
"fallbackPolicy": "FallbackOnNoCapability, FallbackOnFailure",
"fallbackMessage": text
}
response = session.post(f"{RCS_URL}/bundles", json=payload)
response.raise_for_status()
return response.json()
my_numbers = ["46700123456", "46700987654", "456189040623"]
send_smart_messages(my_numbers, "Hej! Detta är ett smart meddelande.")
const apiKey = "DIN_API_NYCKEL";
const rcsUrl = "https://api.ip1.net/v3";
async function sendSmartMessages(recipients: string[], text: string): Promise<unknown> {
const payload: CardMessagePayload = {
brand: "min-butik-ab",
agent: "DIN_AGENTS_ID",
type: "Card",
card: {
title: "Höstkampanj 2026",
content: "Få 20% rabatt på alla varor i vår butik under hela oktober månad. Besök oss idag!",
mediaUrl: "https://example.com/images/hoestkampanj.jpg",
type: "Standalone",
order: 0,
suggestions: [
{
label: "Besök vår butik",
order: 0,
type: "OpenUrlAction",
url: "https://example.com/butik",
},
{
label: "Se fler erbjudanden",
order: 1,
type: "OpenUrlAction",
url: "https://example.com/erbjudanden",
},
],
height: "Medium",
Orientation: "Vertical",
},
recipients,
fallbackPolicy: "FallbackOnNoCapability, FallbackOnFailure",
fallbackMessage: text,
};
const response = await fetch(`${rcsUrl}/bundles`, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`HTTP error! status: ${response.status} - ${errorBody}`);
}
return response.json();
}
// Anrop:
const myNumbers = ["46700123456", "46700987654", "456189040623"];
await sendSmartMessages(myNumbers, "Hej! Detta är ett smart meddelande.");
Övervakning och statuskoder för fallback
När ett meddelande behandlas av fallback-motorn uppdateras dess status kontinuerligt via API:et och dina registrerade webhooks. Det ger dig full spårbarhet i realtid över vilken kanal som faktiskt användes för leverans.
Några viktiga statuskoder att känna till i pipelinen:
- 121 (FallbackPending): RCS-leverans kunde inte bekräftas; meddelandet har förberetts för SMS-fallback.
- 122 (FallbackQueued): Meddelandet har lagts i kö för att skickas via SMS-gateway.
- 221 (FallbackDeliveredToHandset): Meddelandet levererades till mottagarens telefon via en alternativ leveransväg.
- 421 (FallbackRejected): Reservanropet avvisades (t.ex. på grund av ogiltigt nummer eller saknad behörighet).
- 521 (FallbackFailed): Det gick inte att leverera meddelandet varken via RCS eller SMS.
Best Practices för maximal leveranssäkerhet
- Anpassa timeout efter användningsfall: För inloggningskoder och engångslösenord (OTP) bör fallbackTimeOutSeconds sättas lågt (t.ex. 30–60 sekunder) så att kunden slipper vänta. För marknadsföringskampanjer är 300–600 sekunder lämpligt för att ge RCS-nätverket rimlig tid att leverera.
- Inkludera alltid en länk i fallbackMessage: Om ditt RCS-meddelande innehöll en klickbar knapp till en landningssida, se till att motsvarande webbadress skrivs ut i klartext i ditt fallbackMessage.
- Mät kanalfördelningen: Använd statuskoderna för att analysera hur stor andel av dina utskick som når mottagarna via RCS kontra SMS. Det ger värdefulla insikter om hur snabbt RCS-mottagandet växer i din specifika kundbas.