From f6f86e096f7ecd0252f170f72733470b1c82376e Mon Sep 17 00:00:00 2001 From: Avi Goldman Date: Tue, 28 Apr 2026 09:10:59 -0400 Subject: [PATCH] add support for sending transactional in-app messages Add SendInAppRequest class and send_in_app method to APIClient for the POST /v1/send/in_app endpoint. Follows the same pattern as the existing inbox message support. --- customerio/__init__.py | 2 +- customerio/api.py | 47 ++++++++++++++++++++++++++++++++++++++++++ tests/test_api.py | 20 ++++++++++++++++-- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/customerio/__init__.py b/customerio/__init__.py index f7dda1c..29f9d4e 100644 --- a/customerio/__init__.py +++ b/customerio/__init__.py @@ -2,5 +2,5 @@ from customerio.client_base import CustomerIOException from customerio.track import CustomerIO -from customerio.api import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest +from customerio.api import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest, SendInAppRequest from customerio.regions import Regions diff --git a/customerio/api.py b/customerio/api.py index 3474fb9..85ee02b 100644 --- a/customerio/api.py +++ b/customerio/api.py @@ -40,6 +40,12 @@ def send_inbox_message(self, request): resp = self.send_request('POST', self.url + "/v1/send/inbox_message", request) return json.loads(resp) + def send_in_app(self, request): + if isinstance(request, SendInAppRequest): + request = request._to_dict() + resp = self.send_request('POST', self.url + "/v1/send/in_app", request) + return json.loads(resp) + # builds the session. def _build_session(self): session = super()._build_session() @@ -311,3 +317,44 @@ def _to_dict(self): data[name] = value return data + +class SendInAppRequest(object): + '''An object with all the options available for triggering a transactional in-app message''' + def __init__(self, + transactional_message_id=None, + identifiers=None, + disable_message_retention=None, + queue_draft=None, + message_data=None, + send_at=None, + language=None, + ): + + self.transactional_message_id = transactional_message_id + self.identifiers = identifiers + self.disable_message_retention = disable_message_retention + self.queue_draft = queue_draft + self.message_data = message_data + self.send_at = send_at + self.language = language + + def _to_dict(self): + '''Build a request payload from the object''' + field_map = dict( + # field name is the same as the payload field name + transactional_message_id="transactional_message_id", + identifiers="identifiers", + disable_message_retention="disable_message_retention", + queue_draft="queue_draft", + message_data="message_data", + send_at="send_at", + language="language", + ) + + data = {} + for field, name in field_map.items(): + value = getattr(self, field, None) + if value is not None: + data[name] = value + + return data diff --git a/tests/test_api.py b/tests/test_api.py index ea68a55..3bfa878 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,7 +5,7 @@ import sys import unittest -from customerio import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest, Regions, CustomerIOException +from customerio import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest, SendInAppRequest, Regions, CustomerIOException from customerio.__version__ import __version__ as ClientVersion from tests.server import HTTPSTestCase @@ -126,6 +126,22 @@ def test_send_inbox_message(self): ) self.client.send_inbox_message(inbox_message) - + + def test_send_in_app(self): + self.client.http.hooks = dict(response=partial(self._check_request, rq={ + 'method': 'POST', + 'authorization': "Bearer app_api_key", + 'content_type': 'application/json', + 'url_suffix': '/v1/send/in_app', + 'body': {"identifiers": {"id":"customer_1"}, "transactional_message_id": 100} + })) + + in_app = SendInAppRequest( + identifiers={"id":"customer_1"}, + transactional_message_id=100, + ) + + self.client.send_in_app(in_app) + if __name__ == '__main__': unittest.main()