From dd1484106d7d774d9e6a99017c0eaf10f1789866 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Thu, 18 Jun 2026 10:55:20 +0200 Subject: [PATCH 1/2] fix: send batch sent_at in snake case --- .changeset/sweet-ravens-tap.md | 5 +++++ posthog/request.py | 2 +- posthog/test/test_request.py | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 .changeset/sweet-ravens-tap.md diff --git a/.changeset/sweet-ravens-tap.md b/.changeset/sweet-ravens-tap.md new file mode 100644 index 00000000..8138f288 --- /dev/null +++ b/.changeset/sweet-ravens-tap.md @@ -0,0 +1,5 @@ +--- +'pypi/posthog': patch +--- + +Send batch `sent_at` using the backend-supported snake_case field. diff --git a/posthog/request.py b/posthog/request.py index b45f9011..6d38ee0b 100644 --- a/posthog/request.py +++ b/posthog/request.py @@ -228,7 +228,7 @@ def post( """Post the `kwargs` to the API""" log = logging.getLogger("posthog") body = kwargs - body["sentAt"] = datetime.now(tz=timezone.utc).isoformat() + body["sent_at"] = datetime.now(tz=timezone.utc).isoformat() trimmed_host = remove_trailing_slash(normalize_host(host)) url = trimmed_host + cast(str, path) body["api_key"] = api_key diff --git a/posthog/test/test_request.py b/posthog/test/test_request.py index 21d67c98..5348133f 100644 --- a/posthog/test/test_request.py +++ b/posthog/test/test_request.py @@ -111,6 +111,24 @@ def test_post_sends_string_payload_without_gzip(self): self.assertEqual(url, "https://test.posthog.com/batch/") self.assertIsInstance(data, str) + def test_post_sends_snake_case_sent_at(self): + mock_response = requests.Response() + mock_response.status_code = 200 + mock_session = mock.MagicMock() + mock_session.post.return_value = mock_response + + request_module.post( + TEST_API_KEY, + host="https://test.posthog.com", + path="/batch/", + session=mock_session, + batch=[], + ) + + data = json.loads(mock_session.post.call_args.kwargs["data"]) + self.assertIn("sent_at", data) + self.assertNotIn("sentAt", data) + def test_post_sends_bytes_payload_with_gzip(self): mock_response = requests.Response() mock_response.status_code = 200 From e027111b09a3358eaf6c1f65ee941645cbbc7004 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Thu, 18 Jun 2026 11:07:14 +0200 Subject: [PATCH 2/2] address pr review feedback --- posthog/test/test_request.py | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/posthog/test/test_request.py b/posthog/test/test_request.py index 5348133f..d14e2dd7 100644 --- a/posthog/test/test_request.py +++ b/posthog/test/test_request.py @@ -59,6 +59,31 @@ def test_mask_tokens_in_url(url, expected): assert _mask_tokens_in_url(url) == expected +@pytest.mark.parametrize( + "key, expected_present", + [ + ("sent_at", True), + ("sentAt", False), + ], +) +def test_post_sends_snake_case_sent_at(key, expected_present): + mock_response = requests.Response() + mock_response.status_code = 200 + mock_session = mock.MagicMock() + mock_session.post.return_value = mock_response + + request_module.post( + TEST_API_KEY, + host="https://test.posthog.com", + path="/batch/", + session=mock_session, + batch=[], + ) + + data = json.loads(mock_session.post.call_args.kwargs["data"]) + assert (key in data) is expected_present + + class TestRequests(unittest.TestCase): def test_valid_request(self): res = batch_post( @@ -111,24 +136,6 @@ def test_post_sends_string_payload_without_gzip(self): self.assertEqual(url, "https://test.posthog.com/batch/") self.assertIsInstance(data, str) - def test_post_sends_snake_case_sent_at(self): - mock_response = requests.Response() - mock_response.status_code = 200 - mock_session = mock.MagicMock() - mock_session.post.return_value = mock_response - - request_module.post( - TEST_API_KEY, - host="https://test.posthog.com", - path="/batch/", - session=mock_session, - batch=[], - ) - - data = json.loads(mock_session.post.call_args.kwargs["data"]) - self.assertIn("sent_at", data) - self.assertNotIn("sentAt", data) - def test_post_sends_bytes_payload_with_gzip(self): mock_response = requests.Response() mock_response.status_code = 200