{"id":224,"library":"trycourier","title":"Courier (trycourier)","description":"Python SDK for Courier notification API (multi-channel: email, SMS, push, in-app). Current version is 7.9.0. Install name is trycourier (pip install trycourier) but import name changed to courier in v5+ (from courier.client import Courier). The SDK was completely rewritten with Fern code generation in v5, breaking all v4 code.","status":"active","version":"7.9.0","language":"python","source_language":"en","source_url":"https://github.com/trycourier/courier-python","tags":["notifications","email","sms","push","multi-channel","in-app"],"install":[{"cmd":"pip install trycourier","lang":"bash","label":"Standard (note: import name is courier, not trycourier)"}],"dependencies":[{"reason":"Required. Installed automatically.","package":"httpx","optional":false},{"reason":"Required. Installed automatically.","package":"pydantic","optional":false}],"imports":[{"note":"Install with pip install trycourier but import from courier (not trycourier). v4 used from trycourier import Courier with auth_token= and event/recipient params. v5+ uses from courier.client import Courier with authorization_token= and structured message objects.","wrong":"# Old v4 import pattern (broken in v5+):\nfrom trycourier import Courier\nclient = Courier(auth_token='YOUR_TOKEN')\nclient.send(\n    event='notification-id',\n    recipient='recipient-id',\n    data={'name': 'Alice'}\n)","symbol":"Courier","correct":"# Current v5+ API (import from courier, not trycourier)\nfrom courier.client import Courier\nimport courier\n\nclient = Courier(authorization_token='YOUR_COURIER_AUTH_TOKEN')\n\nresponse = client.send(\n    message=courier.ContentMessage(\n        to=courier.UserRecipient(email='user@example.com'),\n        content=courier.ElementalContent(\n            version='2020-01-01',\n            elements=[courier.ElementalNode_Text(content='Hello!')]\n        ),\n        routing=courier.Routing(method='all', channels=['email'])\n    )\n)\nprint(response.request_id)"}],"quickstart":{"code":"# pip install trycourier\nfrom courier.client import Courier\nimport courier\n\nclient = Courier(\n    authorization_token='YOUR_COURIER_AUTH_TOKEN'\n    # or set env var COURIER_AUTH_TOKEN\n)\n\n# Send using a template (workflow)\nresponse = client.send(\n    message=courier.TemplateMessage(\n        template='your-template-id',  # template ID from Courier dashboard\n        to=courier.UserRecipient(\n            email='user@example.com',\n            user_id='user-123'\n        ),\n        data={\n            'name': 'Alice',\n            'action_url': 'https://yourapp.com'\n        }\n    )\n)\nprint('Request ID:', response.request_id)\n\n# Async client\nfrom courier.client import AsyncCourier\nimport asyncio\n\nasync def send():\n    async with AsyncCourier(authorization_token='YOUR_TOKEN') as client:\n        await client.send(message=courier.TemplateMessage(\n            template='your-template-id',\n            to=courier.UserRecipient(email='user@example.com')\n        ))\n\nasyncio.run(send())","lang":"python","description":"v5+ API. Install is trycourier, import is courier. Sync and async clients available."},"warnings":[{"fix":"pip install trycourier then import from courier: from courier.client import Courier","message":"Install name (trycourier) and import name (courier) differ since v5. pip install trycourier then from courier.client import Courier. LLMs frequently generate from trycourier import Courier which raises ImportError on v5+.","severity":"breaking","affected_versions":">= 5.0"},{"fix":"Migrate to: from courier.client import Courier; client = Courier(authorization_token=...); client.send(message=courier.TemplateMessage(template=..., to=courier.UserRecipient(...)))","message":"Complete API rewrite in v5 using Fern code generation. v4 API (Courier(auth_token=), client.send(event=, recipient=, data=)) is completely gone. All v4 code raises ImportError or AttributeError on v5+.","severity":"breaking","affected_versions":">= 5.0"},{"fix":"Replace Courier(auth_token='...') with Courier(authorization_token='...') or set COURIER_AUTH_TOKEN env var.","message":"auth_token= parameter renamed to authorization_token= in v5. Passing auth_token= raises TypeError.","severity":"breaking","affected_versions":">= 5.0"},{"fix":"Use resource-scoped API: client.brands.delete(...), client.lists.get(...), etc.","message":"Resource-scoped methods introduced in v5. Old flat methods like courier.deleteBrands() replaced with courier.brands.delete(). All flat method calls raise AttributeError.","severity":"breaking","affected_versions":">= 5.0"},{"fix":"Set COURIER_AUTH_TOKEN in your environment, or pass authorization_token= explicitly. Verify with: python -c \"import os; print(os.environ.get('COURIER_AUTH_TOKEN'))\"","message":"The COURIER_AUTH_TOKEN environment variable is read automatically if authorization_token= is not passed. Useful for 12-factor apps but can cause silent auth failures if the wrong env var is set.","severity":"gotcha","affected_versions":">= 5.0"}],"env_vars":null,"last_verified":"2026-05-12T12:01:26.307Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"from courier.client import Courier","cause":"The import path for the Courier SDK changed from `trycourier.client` to `courier.client` starting from version 5.0.0.","error":"ModuleNotFoundError: No module named 'trycourier.client'"},{"fix":"client.send_notification(recipient_id=\"RECIPIENT_ID\", event_id=\"EVENT_ID\", data={\"key\": \"value\"})","cause":"The method for sending notifications was renamed from `send_message` (or `send`) to `send_notification` in SDK version 5.0.0.","error":"AttributeError: 'Courier' object has no attribute 'send_message'"},{"fix":"client.send_notification(recipient_id=\"YOUR_RECIPIENT_ID\", event_id=\"YOUR_EVENT_ID\", data={\"key\": \"value\"})","cause":"The `send_notification` method in SDK v5+ requires explicit `recipient_id` and `event_id` arguments, replacing the single `message` dictionary from older versions.","error":"TypeError: send_notification() missing 2 required positional arguments: 'recipient_id' and 'event_id'"},{"fix":"Ensure the `COURIER_AUTH_TOKEN` environment variable is correctly set or pass a valid `authorization_token` when initializing the `Courier` client.","cause":"The Courier API key used for authentication is missing, invalid, or lacks the necessary permissions.","error":"courier.exceptions.CourierAuthError: Not Authorized"}],"ecosystem":"pypi","meta_description":null,"install_score":80,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"36.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"36M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"39.5M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"39M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"31.0M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"31M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"30.6M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"30M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"35.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"35M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}