Introduction to RCS Callbacks

Callbacks are real-time notifications sent to your system whenever an event related to RCS messages occurs. They allow full monitoring of the message lifecycle, from sending to recipient interactions.

Communication Flow

  1. Message Trigger → Your system sends the message via the API
  2. Eventos RCS → The gateway processes and sends the message
  3. Callbacks → Your webhook receives real-time updates

Main Use Cases

  • Delivery and read receipt confirmation, and numbers without RCS support
  • Tracking interactions (clicks, responses)
  • Error and exception handling
  • Collecting metrics and analytics

Callback Parameters

All callbacks share a common structure with the following parameters:

ParâmetroTipoDescrição
referenceStringThe unique ID parameter, which remains unchanged regardless of internal (send) or external (responses, clicks, and calls) events.
campaign_nameStringThe name of the RCS campaign.
event_idStringThis is also an ID parameter, but it changes when there is an external event (e.g., button clicks or text responses). Before that, it remains the same until the message is marked as read. (Typically used for tracking clicks and customer responses).
directionStringoutbound (sending) or inbound (receiving)
session_idStringThe session ID (null for basic or single-type messages)
user_idStringThe recipient’s phone number
timestampStringDate/time of the event (ISO 8601)
channelStringThe channel from which your message was sent. If the phone supports RCS, the channel will be RCS; if the phone doesn’t support it, the channel will be SMS (if fallback is configured).
typeStringEvent identifier, used to identify what was sent and its status. This field is filled based on the direction. In the first case, the type of RCS being sent will appear. In the second case, it will indicate whether the message was delivered, read, or if the user interacted with it, etc.
messageObjectThis field is filled in 3 situations: 1) First callback return, showing the message sent. 2) The message is filled with the customer’s message or the action they took. 3) When we encounter any of the “Exception” cases for fallback sending or errors sent by Google. If it doesn’t fit into any of these cases, it always returns NULL.
varsObjectIf the variable parameters were filled in your send request, the callback return will contain those variables.
statusStringOnly present in cases of duplication blocking. It provides information about the block.

Webhook Events

Text

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "text": {
      "message": String
    }
  }
}

Video

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "video": {
      "url": String
    }
  }
}

Image

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "image": {
      "url": String
    }
  }
}

PDF

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "pdf": {
      "url": String
    }
  }
}

RichCard

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "richCard": {
      "fileUrl": String,
      "title": String,
      "subtitle": String,
      "description":String,
      "suggestions": []
    }
  }
}

Carousel

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "carousel": [
      {
        "fileUrl": String,
        "title": String,
        "subtitle": String,
        "description": String,
        "suggestions": []
      },
      {
        "fileUrl": String,
        "title": String,
        "subtitle": String,
        "description": String,
        "suggestions": [
          {
            "title": String,
            "type": String,
            "value": String
          }
        ]
      }
    ]
  }
}

Status

DELIVERED

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": "inbound",
  "session_id": String,
  "user_id": String,
  "timestamp":String,
  "channel":String,
  "type": "DELIVERED",
  "message": null, || String
  "vars?: {
    "VAR1": String
  }
}

When type: delivered, it means that the message has been sent to the device.

READ

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": "inbound",
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": "READ",
  "message": null || String
}

When type: read, it means that the message has been read.

PREPAID_BLOCKED

{
 "reference": String,
 "campaign_name": String,
 "event_id": String,
 "direction": "inbound",
 "user_id": String,
 "timestamp": String,
 "channel": String,
 "type":"PREPAID_BLOCKED",
 "message":"Limite de créditos do cliente atingido" | "Limite de créditos da conta atingido ${accountId}"
}

When type: PREPAID_BLOCKED means that the sending was blocked due to lack of credits. The message may be “Limite de créditos do cliente atingido” which is when the customer has no credits, or “Limite de créditos da conta atingido accountId” which is when the account used in the trigger that is linked to the customer has no credits. The account ID will be shown in accountId.

suggestionResponse

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": "inbound",
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type":"suggestionResponse",
  "message": {
    "contentType": String,
    "text": {
      "message": String
    }
  }
}

When type: suggestionResponse, it means that the user interacted with the message.

EXCEPTION

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": "outbound",
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": "rcs",
  "type": "EXCEPTION",
  "message": String,
}

Whenever we encounter an Exception, the message property will display one of these responses:

  • Request failed with status code 401: Failed to fetch the authentication token.
  • Request failed with status code 403: Device does not support RCS.
  • Request failed with status code 404: Device does not support RCS.

ERROR

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": "outbound",
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": "rcs",
  "type": "ERROR",
  "message": String,
}

Whenever we encounter an Error, the message property will display one of these responses:

  • Request failed with status code 502: Bad Gateway.
  • Request failed with status code 503: Service Unavailable

Response

TEXT

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type":String,
  "message": {
    "contentType": String,
    "text": {
      "message": String
    }
  }
}

IMAGE

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "contentType": String,
    "text": {
      "message": String
    }
  }
}

VIDEO

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type":String,
  "message": {
    "contentType": String,
    "text": {
      "message": String
    }
  }
}

LOCATION

{
  "reference": String,
  "campaign_name": String,
  "event_id": String,
  "direction": String,
  "session_id": String,
  "user_id": String,
  "timestamp": String,
  "channel": String,
  "type": String,
  "message": {
    "contentType": String,
    "text": {
      "message": String
    }
  }
}

Timeout

The webhook will attempt to be sent to the receiver for up to 10 seconds after an event occurs. If the delivery is unsuccessful, it will proceed to the next retry attempt.

Send Attempt

If the webhook fails (due to a timeout, receiver error, or if the receiver’s response is not an HTTP 200 code), it will be retried up to 10 times. The attempts are made at the following intervals:

  • 1st attempt: 10 seconds;
  • 2nd attempt: 30 seconds;
  • 3rd attempt: 2 minutes;
  • 4th attempt: 10 minutes;
  • 5th attempt: 30 minutes;
  • 6th attempt: 1 hour;
  • 7th attempt: 3 hours;
  • 8th attempt: 6 hours;
  • 9th attempt: 12 hours;
  • 10th attempt: 1 day.

Endpoint Requirements

  • Must return HTTP 200 for confirmation

  • Maximum response time: 10 seconds

  • Must handle duplicate messages (idempotency)

Full Example

{
  "reference": "33ada75c-268c-4ded-989b-126beb201e9c",
  "campaign_name": "Api account pontaltech product 12345 day 26-03-2025",
  "event_id": "33ada75c-268c-4ded-989b-126beb201e9c",
  "direction": "outbound",
  "session_id": "0b34cabc-bd7c-4592-966e-339f642d1933",
  "user_id": "5511991503311",
  "timestamp": "2025-03-26T21:44:13.647Z",
  "channel": "rcs",
  "type": "text",
  "message": {
    "message": "Hi Jhon Doe. This is awesome callback example"
  },
  "vars": {
    "name": "Jhon Doe"
  }
}