Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions mailerlite/sdk/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,37 @@ def delete(self, group_id):

return True if response.status_code == 204 else False

def import_subscribers_to_group(self, group_id, subscribers):
"""
Import bulk subscribers to a group

Provides an ability to import bulk subscribers to a group.
Ref: https://developers.mailerlite.com/api/groups#import-bulk-subscribers-to-group

:param group_id: int Group ID
:param subscribers: list List of subscriber objects to import
:raises: :class: `TypeError` : `group_id` type is not valid
:raises: :class: `TypeError` : `subscribers` type is not valid
:return: JSON array
:rtype: dict
"""

if not isinstance(group_id, int):
raise TypeError(
f"`group_id` type is not valid. Expected `int`, got {type(group_id)}."
)

if not isinstance(subscribers, list):
raise TypeError(
f"`subscribers` type is not valid. Expected `list`, got {type(subscribers)}."
)

return self.api_client.request(
"POST",
f"{self.base_api_url}/{group_id}/subscribers/import",
body={"subscribers": subscribers},
).json()

def get_group_subscribers(self, group_id, **kwargs):
"""
Get subscribers belonging to a group
Expand Down
24 changes: 24 additions & 0 deletions tests/groups_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,30 @@ def test_given_correct_group_id_and_name_when_calling_update_then_group_is_updat
assert set(group_keys).issubset(response["data"].keys())
assert response["data"]["name"] == name

def test_given_incorrect_group_id_when_calling_import_subscribers_to_group_then_type_error_is_returned(
self,
):
with pytest.raises(TypeError):
self.client.groups.import_subscribers_to_group("1234", [])

def test_given_incorrect_subscribers_when_calling_import_subscribers_to_group_then_type_error_is_returned(
self,
):
with pytest.raises(TypeError):
self.client.groups.import_subscribers_to_group(1234, "not-a-list")

@vcr.use_cassette(
"tests/vcr_cassettes/groups-import-subscribers.yml",
filter_headers=["Authorization"],
)
def test_given_correct_parameters_when_calling_import_subscribers_to_group_then_import_is_queued(
self,
):
subscribers = [{"email": "test@example.com", "name": "Test User"}]
response = self.client.groups.import_subscribers_to_group(pytest.entity_id, subscribers)

assert isinstance(response, dict)

def test_given_incorrect_group_id_when_calling_get_group_subscribers_then_type_error_is_returned(
self,
):
Expand Down
48 changes: 48 additions & 0 deletions tests/vcr_cassettes/groups-import-subscribers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
interactions:
- request:
body: '{"subscribers": [{"email": "test@example.com", "name": "Test User"}]}'
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate, zstd
Connection:
- keep-alive
Content-Length:
- '69'
Content-Type:
- application/json
User-Agent:
- MailerLite-Python-SDK-Client
method: POST
uri: https://connect.mailerlite.com/api/groups/165971156405323676/subscribers/import
response:
body:
string: '{"message":"Unauthenticated."}'
headers:
CF-RAY:
- a08656bc39a6278a-PRG
Cache-Control:
- no-cache, private
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 08 Jun 2026 07:56:14 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
access-control-allow-origin:
- '*'
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
x-envoy-upstream-service-time:
- '22'
status:
code: 401
message: Unauthorized
version: 1