-
Notifications
You must be signed in to change notification settings - Fork 2
Unify README structure and content #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
marcos-sinch
wants to merge
4
commits into
main
Choose a base branch
from
chore/DEVEXP-1409-readme-unification
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+174
−89
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
48f8f50
chore: unify README structure and content
marcos-sinch 3ecc6b6
chore: unify README structure and content
marcos-sinch 7cd2a9e
chore: unify README content and structure
marcos-sinch d7f012b
chore: update API links in README for consistency
marcos-sinch File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,164 +1,224 @@ | ||
| # Sinch Python SDK | ||
|
|
||
| [](https://github.com/sinch/sinch-sdk-python/blob/main/LICENSE) | ||
|
|
||
|
|
||
| [](https://www.python.org/downloads/release/python-390/) | ||
| [](https://www.python.org/downloads/release/python-3100/) | ||
| [](https://www.python.org/downloads/release/python-3110/) | ||
| [](https://www.python.org/downloads/release/python-3120/) | ||
| [](https://www.python.org/downloads/release/python-3130/) | ||
| [](https://www.python.org/downloads/release/python-3140/) | ||
|
|
||
| [](https://www.python.org/) [](https://pypi.org/project/sinch/) [](https://github.com/sinch/sinch-sdk-python/blob/main/LICENSE) | ||
|
|
||
|
|
||
| Here you'll find documentation related to the Sinch Python SDK, including how to install it, initialize it, and start developing Python code using Sinch services. | ||
|
|
||
| To use Sinch services, you'll need a Sinch account and access keys. You can sign up for an account and create access keys at [dashboard.sinch.com](https://dashboard.sinch.com). | ||
|
|
||
| For more information on the Sinch APIs on which this SDK is based, refer to the official [developer documentation portal](https://developers.sinch.com). | ||
| For more information on the SDK, refer to the dedicated [Python SDK documentation](https://developers.sinch.com/docs/sdks/python) section, and for the Sinch APIs on which this SDK is based, refer to the official [developer documentation portal](https://developers.sinch.com). | ||
|
|
||
|
|
||
| ## Table of contents: | ||
|
|
||
| - [Prerequisites](#prerequisites) | ||
| - [Installation](#installation) | ||
| - [Supported APIs](#supported-apis) | ||
| - [Getting started](#getting-started) | ||
| - [Logging](#logging) | ||
| - [Handling Exceptions](#handling-exceptions) | ||
| - [Custom HTTP client implementation](#custom-http-client-implementation) | ||
| - [Third-party dependencies](#third-party-dependencies) | ||
| - [Examples](#examples) | ||
| - [Changelog and Migration](#changelog--migration) | ||
| - [License](#license) | ||
| - [Contact](#contact) | ||
|
|
||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Python in one of the supported versions - 3.9, 3.10, 3.11, 3.12, 3.13, 3.14 | ||
| - pip | ||
| - Sinch account | ||
| - [Python](https://www.python.org/) in one of the supported versions - [3.9](https://www.python.org/downloads/release/python-390/), [3.10](https://www.python.org/downloads/release/python-3100/), [3.11](https://www.python.org/downloads/release/python-3110/), [3.12](https://www.python.org/downloads/release/python-3120/), [3.13](https://www.python.org/downloads/release/python-3130/), [3.14](https://www.python.org/downloads/release/python-3140/) | ||
| - [pip](https://pip.pypa.io/en/stable/) | ||
| - [Sinch account](https://dashboard.sinch.com/) | ||
|
|
||
| > **Warning**: | ||
| > This SDK is intended for server-side (backend) use only. Do not use it in front-end or client-side applications (web, mobile, or desktop), regardless of language or framework. Doing so can expose your Sinch credentials to end-users. | ||
|
|
||
| ## Installation | ||
|
|
||
| You can install this package by typing: | ||
| `pip install sinch` | ||
| Run the following command to install the SDK: | ||
|
|
||
| ## Products | ||
| ```bash | ||
| pip install sinch | ||
| ``` | ||
|
|
||
| The Sinch client provides access to the following Sinch products: | ||
| - Numbers API | ||
| - SMS API | ||
| - Conversation API (beta release) | ||
|
|
||
| ## Supported APIs | ||
|
|
||
| ## Getting started | ||
|
|
||
| | API Category | API Name | | ||
| |-------------------|-----------------------------| | ||
| | Messaging | [Conversation API](https://developers.sinch.com/docs/conversation/) | | ||
| | Messaging | [SMS](https://developers.sinch.com/docs/sms/) | | ||
| | Numbers | [Numbers API](https://developers.sinch.com/docs/numbers/) | | ||
| | Verification | [Number Lookup API](https://developers.sinch.com/docs/number-lookup/) | | ||
|
|
||
| ### Client initialization | ||
|
|
||
| To establish a connection with the Sinch backend, you must provide credentials based on the API you intend to use. | ||
| For security best practices, avoid hardcoding credentials — retrieve them from environment variables instead. | ||
| ## Getting started | ||
|
|
||
| > **Note:** `sms_region` and `conversation_region` no longer have defaults and **must** be set before | ||
| > calling those APIs—omitting them will cause a runtime error. See [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) for details. | ||
|
|
||
| ### Client initialization | ||
|
|
||
| #### SMS API | ||
| To start using the SDK, initialize the main client class. This client gives you access to all the SDK services: | ||
|
|
||
| The SMS API supports two authentication methods. `sms_region` is required for both and has no default. | ||
| ```python | ||
| import os | ||
| from sinch import SinchClient | ||
|
|
||
| **Project auth (OAuth2)** | ||
| # Warning: project authentication, check if the API used supports it or has additional parameters | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. About the |
||
| sinch_client = SinchClient( | ||
| project_id=os.environ["SINCH_PROJECT_ID"], | ||
| key_id=os.environ["SINCH_KEY_ID"], | ||
| key_secret=os.environ["SINCH_KEY_SECRET"], | ||
| ) | ||
| ``` | ||
|
|
||
| The SDK automatically exchanges your key ID and key secret for a short-lived OAuth2 token and refreshes it automatically on expiry. | ||
| Supported regions: `us`, `eu`, `br`. | ||
| Get `project_id`, `key_id` and `key_secret` from the [Access keys](https://dashboard.sinch.com/settings/access-keys) page in your Sinch dashboard (`key_secret` is shown only once, at creation time). It's highly recommended to not hardcode these credentials: load them from environment variables for local development, and from a secret manager in production. | ||
|
|
||
| In your [Account dashboard](https://dashboard.sinch.com/settings/access-keys), you will find your `projectId` and access keys composed of pairs of `keyId` / `keySecret`. | ||
| This snippet is the common starting point for every API. Some APIs have a different initialization or need extra parameters (for example, a region), see the section for each API. | ||
|
|
||
| > **Note:** the `keySecret` is visible only when you create the Access Key. Store it safely and create a new Access Key if you have lost it. | ||
| ### Conversation API | ||
|
|
||
| ```python | ||
| from sinch import SinchClient | ||
| The Conversation API is regionalized. To use this API, the `conversation_region` parameter is required: | ||
|
|
||
| ```python | ||
| sinch_client = SinchClient( | ||
| project_id="project_id", | ||
| key_id="key_id", | ||
| key_secret="key_secret", | ||
| sms_region="us" | ||
| project_id=os.environ["SINCH_PROJECT_ID"], | ||
| key_id=os.environ["SINCH_KEY_ID"], | ||
| key_secret=os.environ["SINCH_KEY_SECRET"], | ||
| conversation_region="eu", | ||
| ) | ||
| ``` | ||
|
|
||
| **Service Plan ID auth (legacy)** | ||
|
|
||
| Uses a static bearer token that never expires. | ||
| Support all regions: `us`, `eu`, `br`, `ca`, `au`. | ||
| #### Sinch Events | ||
|
|
||
| In your [Service APIs dashboard](https://dashboard.sinch.com/sms/api/services), you will find your `servicePlanId` and `apiToken` (bearer token). | ||
| The Conversation API delivers asynchronous Sinch Events to the Event Destination URL you configure for your app in the [Conversation dashboard](https://dashboard.sinch.com/convapi/apps). `validate_authentication_header` confirms a request comes from Sinch and `parse_event` turns its payload into a typed event object; `headers` and `raw_body` are the incoming request's headers and raw body: | ||
|
|
||
| ```python | ||
| from sinch import SinchClient | ||
| sinch_events = sinch_client.conversation.sinch_events(SINCH_EVENT_SECRET) | ||
| is_valid = sinch_events.validate_authentication_header(headers=headers, json_payload=raw_body) | ||
| event = sinch_events.parse_event(raw_body, headers) | ||
| ``` | ||
|
|
||
| `SINCH_EVENT_SECRET` is optional and set per app in the [Conversation dashboard](https://dashboard.sinch.com/convapi/apps). `parse_event` works without validating the request, but then its origin can't be verified, so calling `validate_authentication_header` (which returns `True`/`False`) is recommended in production. | ||
|
|
||
| You can find a complete example in [examples/sinch_events/conversation_api](./examples/sinch_events/conversation_api). | ||
|
|
||
| ### SMS API | ||
|
|
||
| > **Warning:** the SMS API is end-of-sale. For new integrations, prefer the [Conversation API](#conversation-api). | ||
|
|
||
| The SMS API is regionalized: set `sms_region` to the region where your SMS account is hosted. The accepted values are `us`, `eu`, `au`, `br` and `ca`, and the region also determines which credentials you can use: | ||
|
|
||
| - **Project access keys** — available only in the `us` and `eu` regions. Use the same `project_id`, `key_id` and `key_secret` as the common client, plus `sms_region`: | ||
|
|
||
| ```python | ||
| sinch_client = SinchClient( | ||
| service_plan_id="service_plan_id", | ||
| sms_api_token="api_token", | ||
| sms_region="us" | ||
| project_id=os.environ["SINCH_PROJECT_ID"], | ||
| key_id=os.environ["SINCH_KEY_ID"], | ||
| key_secret=os.environ["SINCH_KEY_SECRET"], | ||
| sms_region="us", | ||
| ) | ||
| ``` | ||
|
|
||
| #### Conversation API - Project auth (OAuth2) | ||
| > **SMS authentication for new projects** | ||
| > | ||
| > Projects created after the SMS API end-of-sale (`15/04/26`) cannot use | ||
| > project access keys — the SMS API requests return `401 Unauthorized`. | ||
| > | ||
| > If you encounter this issue, consider the following options: | ||
| > | ||
| > 1. Use service plan credentials (`service_plan_id` + `sms_api_token`) | ||
| > 2. Use the Conversation API, which works with project access keys. | ||
| > 3. Contact your account manager | ||
|
|
||
| `conversation_region` is required and has no default. | ||
| Supported regions: `us`, `eu`, `br`. | ||
|
|
||
| > **Why region matters:** The Conversation API stores and routes data within the selected region for regulatory compliance. Choose the region that matches your data residency requirements. | ||
| - **Service plan** — available in all regions (`us`, `eu`, `au`, `br`, `ca`). Use a `service_plan_id` and `sms_api_token`, both available on the [Service APIs dashboard](https://dashboard.sinch.com/sms/api/services): | ||
|
|
||
| ```python | ||
| from sinch import SinchClient | ||
|
|
||
| sinch_client = SinchClient( | ||
| project_id="project_id", | ||
| key_id="key_id", | ||
| key_secret="key_secret", | ||
| conversation_region="eu" | ||
| service_plan_id=os.environ["SINCH_SERVICE_PLAN_ID"], | ||
| sms_api_token=os.environ["SINCH_SMS_API_TOKEN"], | ||
| sms_region="us", | ||
| ) | ||
| ``` | ||
|
|
||
| > **SMS integration note:** If you also use the SMS API, `sms_region` and `conversation_region` **must match**. Mismatched regions will cause delivery failures. | ||
| > **Note:** if you use both the SMS and the [Conversation API](#conversation-api) | ||
| > from the same client, set `sms_region` and `conversation_region` to the same | ||
| > region. Mismatched regions cause delivery failures. | ||
|
|
||
| #### Other APIs - Project auth (OAuth2) | ||
| #### Sinch Events | ||
|
|
||
| These APIs are not regionalized and use project-based auth. | ||
| The SMS API delivers asynchronous Sinch Events to an Event Destination, whose URL is set per batch with the `event_destination_target` parameter on the send, update and replace operations (for example `sinch_client.sms.batches.send_sms`). `validate_authentication_header` confirms a request comes from Sinch and `parse_event` turns its payload into a typed event object; `headers` and `raw_body` are the incoming request's headers and raw body: | ||
|
|
||
| ```python | ||
| from sinch import SinchClient | ||
| sinch_events = sinch_client.sms.sinch_events(SINCH_EVENT_SECRET) | ||
| is_valid = sinch_events.validate_authentication_header(headers=headers, json_payload=raw_body) | ||
| event = sinch_events.parse_event(raw_body, headers) | ||
| ``` | ||
|
|
||
| sinch_client = SinchClient( | ||
| project_id="project_id", | ||
| key_id="key_id", | ||
| key_secret="key_secret", | ||
| ) | ||
| Signature authentication for SMS events must be enabled for your account by your account manager; until then the signature headers are absent and `parse_event` can be used on its own. See the [SMS events documentation](https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/section/Callbacks). | ||
|
|
||
| You can find a complete example in [examples/sinch_events/sms_api](./examples/sinch_events/sms_api). | ||
|
|
||
| ### Numbers API | ||
|
|
||
| The Numbers API needs no extra parameters, use the [common client](#client-initialization) based in project authentication shown above. | ||
|
|
||
| #### Sinch Events | ||
|
|
||
| The Numbers API delivers asynchronous Sinch Events to the Event Destination you configure through `sinch_client.numbers.event_destinations`. `validate_authentication_header` confirms a request comes from Sinch and `parse_event` turns its payload into a typed event object; `headers` and `raw_body` are the incoming request's headers and raw body: | ||
|
|
||
| ```python | ||
| sinch_events = sinch_client.numbers.sinch_events(SINCH_EVENT_SECRET) | ||
| is_valid = sinch_events.validate_authentication_header(headers=headers, json_payload=raw_body) | ||
| event = sinch_events.parse_event(raw_body, headers) | ||
| ``` | ||
|
|
||
| ## Logging | ||
| `SINCH_EVENT_SECRET` is the value configured on the Event Destination. `parse_event` works without validating the request, but then its origin can't be verified, so calling `validate_authentication_header` is recommended in production. | ||
|
|
||
| Logging configuration for this SDK utilizes following hierarchy: | ||
| 1. If no configuration was provided via `logger_name` or `logger` configurable, SDK will inherit configuration from the root logger with the `Sinch` prefix. | ||
| 2. If `logger_name` configurable was provided, SDK will use logger related to that name. For example: `myapp.sinch` will inherit configuration from the `myapp` logger. | ||
| 3. If `logger` (logger instance) configurable was provided, SDK will use that particular logger for all its logging operations. | ||
| You can find a complete example in [examples/sinch_events/numbers_api](./examples/sinch_events/numbers_api). | ||
|
|
||
| If all logging returned by this SDK needs to be disabled, usage of `NullHandler` provided by the standard `logging` module is advised. | ||
| ### Number Lookup API | ||
|
|
||
| The Number Lookup API needs no extra parameters, use the [common client](#client-initialization) based in project authentication shown above. | ||
|
|
||
|
|
||
|
|
||
| ## Sample apps | ||
|
|
||
| Usage example of the Numbers API via [`VirtualNumbers`](sinch/domains/numbers/virtual_numbers.py) on the client (`sinch_client.numbers`)—`list()` returns your project’s active virtual numbers: | ||
| ### Your First Request | ||
|
|
||
| Once your client is configured, you can send your first message. The example below uses the Conversation API to send a simple text message over SMS. Replace CONVERSATION_APP_ID with your app ID and RECIPIENT_PHONE_NUMBER with the recipient's phone number: | ||
|
|
||
| ```python | ||
| paginator = sinch_client.numbers.list( | ||
| region_code="US", | ||
| number_type="LOCAL", | ||
| response = sinch_client.conversation.messages.send( | ||
| app_id="CONVERSATION_APP_ID", | ||
| message={ | ||
| "text_message": { | ||
| "text": "[Python SDK: Conversation Message] Sample text message", | ||
| }, | ||
| }, | ||
| recipient_identities=[ | ||
| { | ||
| "channel": "SMS", | ||
| "identity": "RECIPIENT_PHONE_NUMBER", | ||
| } | ||
| ], | ||
| ) | ||
| for active_number in paginator.iterator(): | ||
| print(active_number) | ||
|
|
||
| print(f"Successfully sent message.\n{response}") | ||
| ``` | ||
|
|
||
| Returned values are [Pydantic](https://docs.pydantic.dev/) model instances (for example [`ActiveNumber`](sinch/domains/numbers/models/v1/response/active_number.py)), including fields such as `phone_number`, `region_code`, `type`, and `capabilities`. | ||
| ## Logging | ||
|
|
||
| Logging configuration for this SDK utilizes following hierarchy: | ||
| 1. If no configuration was provided via `logger_name` or `logger` configurable, SDK will inherit configuration from the root logger with the `Sinch` prefix. | ||
| 2. If `logger_name` configurable was provided, SDK will use logger related to that name. For example: `myapp.sinch` will inherit configuration from the `myapp` logger. | ||
| 3. If `logger` (logger instance) configurable was provided, SDK will use that particular logger for all its logging operations. | ||
|
|
||
| More examples live under [examples/snippets](examples/snippets) on the `main` branch. | ||
| If all logging returned by this SDK needs to be disabled, usage of `NullHandler` provided by the standard `logging` module is advised. | ||
|
|
||
| ### Handling exceptions | ||
| ## Handling exceptions | ||
|
|
||
| Each API throws a custom, API related exception for an unsuccessful backed call. | ||
|
|
||
|
|
@@ -178,7 +238,6 @@ except NumbersException as err: | |
|
|
||
| For handling all possible exceptions thrown by this SDK use `SinchException` (superclass of all Sinch exceptions) from `sinch.core.exceptions`. | ||
|
|
||
|
|
||
| ## Custom HTTP client implementation | ||
|
|
||
| By default, the HTTP implementation uses the `requests` library. | ||
|
|
@@ -241,9 +300,35 @@ sinch_client.configuration.transport = MyHTTPImplementation( | |
| ) | ||
| ``` | ||
|
|
||
| Note: Asynchronous HTTP clients are not supported. | ||
| The transport must be a synchronous implementation. | ||
| > **Note:** Asynchronous HTTP clients are not supported. The transport must be | ||
| > a synchronous implementation. | ||
|
|
||
|
|
||
| ## Third-party dependencies | ||
| The SDK relies on the following third-party dependencies: | ||
| - [requests](https://requests.readthedocs.io/): HTTP client used as the default transport for all API calls. | ||
| - [pydantic](https://docs.pydantic.dev/): Data validation and serialization for request and response models. | ||
|
|
||
| ## Examples | ||
|
|
||
| You can find: | ||
| - a Python example of each request in the [examples/snippets](./examples/snippets) folder. | ||
| - getting started guides for specific use cases in the [examples/getting-started](./examples/getting-started) folder. | ||
| - server-side event handling examples in the [examples/sinch_events](./examples/sinch_events) folder. | ||
|
|
||
| ## Changelog & Migration | ||
|
|
||
| For information about the latest changes in the SDK, please refer to the [CHANGELOG](CHANGELOG.md) file | ||
| and the [MIGRATION_GUIDE](MIGRATION_GUIDE.md) for instructions on how to update your code when upgrading to a new major version of the SDK. | ||
|
|
||
| ## License | ||
|
|
||
| This project is licensed under the Apache License. See the [LICENSE](LICENSE) file for the license text. | ||
| This project is licensed under the Apache License. | ||
|
|
||
| See the [LICENSE](LICENSE) file for the license text. | ||
|
|
||
|
|
||
| ## Contact | ||
|
|
||
| Developer Experience engineering team: [team-developer-experience@sinch.com](mailto:team-developer-experience@sinch.com) | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.