Recipient history
Look up the full conversation history for one phone number tied to
your account. Every outbound RCS message the account ever sent to
that phone (broadcast, one-off /messages/send, composer test
send), plus every inbound reply the phone sent back, lands on the
same page.
Typical uses:
- Support, customer says "I didn't get the OTP" → paste the phone and see whether the message shipped, was delivered, was read, or failed with a reason.
- Compliance, one-click "Opt out of all bots" from the recipient page (owner + operator only) hard-suppresses every future send to that phone.
- Reply capture, the
direction: "in"rows carry the customer's free-form reply text, file, or location payload so the operator can review conversational threads without opening the inbox page.
Endpoint
GET /api/v1/rcs/recipients/:phone:phone accepts every reasonable shape and is normalised
server-side to E.164 with +91 as the default country code:
An unparseable phone returns 400 code=bad_phone.
Query parameters
Response
{
"success": true,
"phone": "+919876543210",
"first_seen": "2026-06-01T09:12:04Z",
"last_seen": "2026-07-14T14:22:41Z",
"total_out": 47,
"total_in": 3,
"on_opt_out": false,
"kpis": {
"sent": 47,
"delivered": 43,
"read": 31,
"clicked": 12,
"failed": 4,
"click_rate": 27.9
},
"messages": [
{
"id": "rm-msg-01H8Z7…",
"direction": "out",
"source": "broadcast",
"source_id": "b12dcb…",
"source_name": "Diwali Sale 2026",
"bot_id": "…",
"bot_name": "acme_promotions",
"template_id": "…",
"template_name": "diwali_promo_v3",
"status": "delivered",
"sent_at": "2026-07-14T14:22:41Z",
"delivered_at": "2026-07-14T14:22:44Z",
"read_at": "2026-07-14T15:01:12Z",
"payload_json": { "…": "…" }
},
{
"id": "in-msg-…",
"direction": "in",
"source": "inbound",
"source_name": "Yes, please send me the coupon",
"status": "received",
"sent_at": "2026-07-14T15:04:07Z",
"payload_json": { "text": "Yes, please send me the coupon", "reply_to": "rm-msg-01H8Z7…" }
}
],
"next_before": "2026-06-14T09:12:04Z"
}direction,"out"for broadcasts / one-off / test sends,"in"for inbound replies.source,"broadcast","one_off","test", or"inbound". Broadcasts namedone-off:*are internal one-off send rows and surface assource: "one_off",source_name: "One-off send".kpis, computed across the entire recipient history (before any filters land). The sidebar counters on the panel are unaffected by the activestatus/direction/ date filters.payload_json, the message body as it was sent (outbound) or the reply metadata (inbound:text/file_uri/location).on_opt_out/opt_out_reason, true when the phone is on the account's opt-out list. Reasons includejiocx_optout(added for you when a delivery report says the person opted out) andmanual.
Pagination
Pass the response's next_before as ?before=… on the next call
to page backward through the timeline. Pagination is purely
cursor-based, no numeric page counter.
Timeline reads look back 90 days. Broadcasts older than that are elided from the recipient page to keep the read bounded.
Team-member scoping
Team-member sessions carry a bots claim in the JWT. Outbound
rows tied to a bot outside that scope are filtered out at read
time, a member with access to bot_A only will never see rows
for messages sent from bot_B, even to the same phone.
Inbound rows are account-scoped (a reply is not tied to one bot) and are visible to every role.
Opt-out gate
The panel's "Opt out of all bots" button hits the existing
POST /api/v1/rcs/opt-out endpoint, which is operator-only.
Viewers see the timeline but not the button; the endpoint itself
returns 403 code=not_operator if the caller is a viewer.
Adding a phone here silently drops it from every future broadcast on the account. See opt-out list for the reason codes and CSV import.