RCS Send Template API
Base URL: https://app.quickreply.ai
Send an approved RCS template to a recipient. The request carries only the dynamic values for the template — the structure (which components exist, their {{n}} placeholders and paramLength) lives on the stored template and is resolved by templateId.
POST https://app.quickreply.ai/api/v4/external/template-message/rcs/send
Authentication
External secret-key flow, via headers:
x-client-id
Company id
Click the profile/account name in the bottom-left corner of the QuickReply dashboard. In the menu that opens, the Company ID is displayed directly below the company name.
x-secret-key
Company secret key
You can find client-id of your account in Settings > Developers > API credentials
Content-Type
application/json
Request body
to*
string
Recipient phone number in E.164 format, e.g. +919800000000.
templateId*
string
You can find the template id by clicking on the 3 dots at the right of template block and clicking "Copy Template Id"
The stored RCS template's _id. Must be an APPROVED template.
templateParams (Optional)
object
Dynamic values for the template. Send only the fields the template needs (see below).
customEngage (Optional)
object
Follow-up trigger fired on custom engagement.
buttonEngage (Optional)
object
Follow-up trigger fired on button click.
templateParams
Send only what the matched template requires. All fields are optional at the schema level; the template's structure determines what is actually needed.
headerParam
{ type, value, filename?, size? }
type ∈ IMAGE / VIDEO / DOCUMENT. value must be a valid URL (the media link). Required for media and carousel-card headers. filename applies to DOCUMENT (defaults to document.pdf).
bodyParams
[{ value }]
Count must equal the body's paramLength, in {{1}},{{2}},… order.
titleParams
[{ value }]
Count must equal the title's paramLength.
buttonParams
[{ value, index, key? }]
index = button position in the template. key is used for VIEW_LOCATION (lat / long) and CALENDAR (eventTitle / eventDescription / startDateTime / endDateTime).
suggestionParams
[{ value, index, key? }]
Same shape as buttonParams, for suggestion chips.
carouselParams
[{ cardIndex, headerParam, bodyParams?, titleParams?, buttonParams? }]
One entry per card; each card's headerParam is required.
Media is mandatory for interactive templates. Any template that defines buttons or suggestions must also carry a media header (
IMAGE/VIDEO/DOCUMENT). Every send for such a template must include aheaderParamwith a valid media URL — this holds even for static buttons (QUICK_REPLY/SHARE_LOCATION) that otherwise take no value.
Params that need nothing sent (but still require the media header above):
Static text templates with no buttons/suggestions (
paramLength: 0) — omitbodyParamsor send[]; no header needed.QUICK_REPLY/SHARE_LOCATIONbuttons and suggestions — nobuttonParams/suggestionParamsvalue.URL buttons — only need a
buttonParamwhen the URL contains{{1}}. Dynamic URL buttons whose URL includes the template'sshortLinkDomainare auto-shortened via swift-link.
customEngage / buttonEngage
Passed through and attached to the outgoing message (channel.custom_engage / channel.button_engage). For each object supply either playbook or event, not both.
playbook
string
Playbook id to run on engagement.
event
string
Event name to fire on engagement.
Response
200 OK
Examples
The examples below cover every send-time scenario. Substitute <client-id>, <secret-key>, and <template-id>.
1. Text body with dynamic params
Body-only template "Hello {{1}}!", no buttons — so no media header. Static text templates work the same way with bodyParams: [].
2. Dynamic URL button (with mandatory media header)
For a URL button whose url is "<https://example.link/{{1}>}". Because the template has a button, a media headerParam is required.
3. Keyed buttons — VIEW_LOCATION and CALENDAR (with mandatory media header)
Dynamic fields on special button types are passed via key at the button's index. A VIEW_LOCATION button uses lat / long; a CALENDAR button uses the event keys shown here. The media headerParam is required because the template has buttons.
4. Media header — IMAGE / VIDEO / DOCUMENT
One shape for all three. Set type to IMAGE, VIDEO, or DOCUMENT; value must be a valid media URL. DOCUMENT may include filename.
For
DOCUMENT:"headerParam": { "type": "DOCUMENT", "value": "<https://cdn.example.com/doc.pdf>", "filename": "invoice.pdf" }
5. Carousel — multiple cards
One carouselParams entry per card; each card's headerParam is required.
6. With engagement follow-ups
customEngage / buttonEngage attach to any template. Use playbook or event per object. (If the template defines buttons, include the media headerParam as noted above.)
Errors (400 / 403)
Unknown channel
Invalid channel. Supported: rcs
Missing to or templateId
to and templateId are required
to not a valid phone number
to must be a valid phone number
templateParams fails schema (e.g. headerParam.value not a URL)
Invalid templateParams
Body param count mismatch
Body parameter count mismatch: expected N, received M
Body requires params, none sent
Body requires N parameter(s), but none were provided
Media header param missing
Header component requires a parameter with media link...
Carousel card header missing
Carousel card at index N requires a header parameter with media link
Dynamic URL button without value
URL button "..." requires a variable parameter, but none was provided
Keyed dynamic field missing
... has dynamic '<field>' field but no variable with key '<field>' was provided
Template not approved
Template is not approved (status: ...)
Last updated