diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ae6ec60
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,48 @@
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+name: Release to PyPI
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup Python # Set Python version
+ uses: actions/setup-python@v3
+ with:
+ python-version: 3.11
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip poetry
+ poetry config virtualenvs.in-project --unset
+ make install
+
+ - name: Build
+ run: |
+ make build
+
+ - name: Format
+ run: |
+ make format
+
+ - name: Get the version
+ id: get_version
+ run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ steps.get_version.outputs.VERSION }}
+ path: dist
+
+ - name: Release to PyPI
+ run: |
+ pip install twine
+ twine upload -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --verbose dist/*
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0fc4953
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,68 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+venv/
+.venv/
+.python-version
+.pytest_cache
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+#Ipython Notebook
+.ipynb_checkpoints
+
+tests/
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f7ecb5c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 AfterShip
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a867ce1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+.PHONY: build
+
+install:
+ poetry install
+
+test:
+ poetry run pytest tests/ -v
+
+record:
+ poetry run pytest tests/ --vcr-record=new_episodes
+
+format:
+ poetry run ruff check --fix
+ poetry run ruff format
+
+build:
+ poetry build
diff --git a/README.md b/README.md
index 8baed55..515e9f1 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,269 @@
-# tracking-sdk-python
\ No newline at end of file
+# AfterShip Tracking API library for Python
+
+This library allows you to quickly and easily use the AfterShip Tracking API via Python.
+
+For updates to this library, see our [GitHub release page](https://github.com/AfterShip/tracking-sdk-python/releases).
+
+If you need support using AfterShip products, please contact support@aftership.com.
+
+## Table of Contents
+
+- [AfterShip Tracking API library for Python](#aftership-tracking-api-library-for-python)
+ - [Table of Contents](#table-of-contents)
+ - [Before you begin](#before-you-begin)
+ - [API and SDK Version](#api-and-sdk-version)
+ - [Quick Start](#quick-start)
+ - [Installation](#installation)
+ - [Constructor](#constructor)
+ - [Example](#example)
+ - [Rate Limiter](#rate-limiter)
+ - [Error Handling](#error-handling)
+ - [Error List](#error-list)
+ - [Endpoints](#endpoints)
+ - [/trackings](#trackings)
+ - [/couriers](#couriers)
+ - [/estimated-delivery-date](#estimated-delivery-date)
+ - [Help](#help)
+ - [License](#license)
+
+
+## Before you begin
+
+Before you begin to integrate:
+
+- [Create an AfterShip account](https://admin.aftership.com/).
+- [Create an API key](https://organization.automizely.com/api-keys).
+- [Install Python](https://www.python.org/downloads/) version 3.8 or later.
+
+### API and SDK Version
+
+Each SDK version is designed to work with a specific API version. Please refer to the table below to identify the supported API versions for each SDK version, ensuring you select the appropriate SDK version for the API version you intend to use.
+
+| SDK Version | Supported API Version | Branch |
+| ----------- | --------------------- | ------------------------------------------------------------- |
+| 4.x.x | 2024-10 | https://github.com/AfterShip/tracking-sdk-python/tree/2024-10 |
+| 3.x.x | 2024-07 | https://github.com/AfterShip/tracking-sdk-python/tree/2024-07 |
+| 2.x.x | 2024-04 | https://github.com/AfterShip/tracking-sdk-python/tree/2024-04 |
+| <=1.x.x | Legacy API | https://github.com/AfterShip/aftership-sdk-python |
+
+## Quick Start
+
+### Installation
+```bash
+pip install aftership-tracking-sdk
+```
+
+
+## Constructor
+
+Create AfterShip instance with options
+
+| Name | Type | Required | Description |
+| ---------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
+| api_key | string | ✔ | Your AfterShip API key |
+| auth_type | enum | | Default value: `auth.ApiKey`
AES authentication: `auth.Aes`
RSA authentication: `auth.Rsa` |
+| api_secret | string | | Required if the authentication type is `auth.Aes` or `auth.Rsa` |
+| domain | string | | AfterShip API domain. Default value: https://api.aftership.com |
+| user_agent | string | | User-defined user-agent string, please follow [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#field.user-agent) format standard. |
+| proxy | string | | HTTP proxy URL to use for requests.
Default value: `null`
Example: `http://192.168.0.100:8888` |
+| max_retry | number | | Number of retries for each request. Default value: 2. Min is 0, Max is 10. |
+| timeout | number | | Timeout for each request in milliseconds. |
+
+### Example
+
+```python
+import tracking
+from tracking import exceptions
+from tracking import auth
+
+try:
+ sdk = tracking.Client(
+ tracking.Configuration(
+ api_key="YOUR_API_KEY",
+ authentication_type=auth.ApiKey,
+ )
+ )
+ result = sdk.tracking.get_tracking_by_id("")
+ print(result)
+except exceptions.InvalidOptionError:
+ pass
+except exceptions.InvalidApiKeyError:
+ pass
+except exceptions.RateLimitExceedError:
+ pass
+```
+
+## Rate Limiter
+
+See the [Rate Limit](https://www.aftership.com/docs/tracking/2024-10/quickstart/api-quick-start) to understand the AfterShip rate limit policy.
+
+## Error Handling
+
+The SDK will return an error object when there is any error during the request, with the following specification:
+
+| Name | Type | Description |
+| ------------- | ------ | ------------------------------ |
+| message | string | Detail message of the error |
+| code | enum | Error code enum for API Error. |
+| meta_code | number | API response meta code. |
+| status_code | number | HTTP status code. |
+| response_body | string | API response body. |
+
+
+### Error List
+
+| code | meta_code | status_code | message |
+| --------------------------------- | --------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| INVALID_REQUEST | 400 | 400 | The request was invalid or cannot be otherwise served. |
+| INVALID_JSON | 4001 | 400 | Invalid JSON data. |
+| TRACKING_ALREADY_EXIST | 4003 | 400 | Tracking already exists. |
+| TRACKING_DOES_NOT_EXIST | 4004 | 404 | Tracking does not exist. |
+| TRACKING_NUMBER_INVALID | 4005 | 400 | The value of tracking_number is invalid. |
+| TRACKING_REQUIRED | 4006 | 400 | tracking object is required. |
+| TRACKING_NUMBER_REQUIRED | 4007 | 400 | tracking_number is required. |
+| VALUE_INVALID | 4008 | 400 | The value of [field_name] is invalid. |
+| VALUE_REQUIRED | 4009 | 400 | [field_name] is required. |
+| SLUG_INVALID | 4010 | 400 | The value of slug is invalid. |
+| MISSING_OR_INVALID_REQUIRED_FIELD | 4011 | 400 | Missing or invalid value of the required fields for this courier. Besides tracking_number, also required: [field_name] |
+| BAD_COURIER | 4012 | 400 | The error message will be one of the following:
1. Unable to import shipment as the carrier is not on your approved list for carrier auto-detection. Add the carrier here: https://admin.aftership.com/settings/couriers
2. Unable to import shipment as we don’t recognize the carrier from this tracking number.
3. Unable to import shipment as the tracking number has an invalid format.
4. Unable to import shipment as this carrier is no longer supported.
5. Unable to import shipment as the tracking number does not belong to a carrier in that group. |
+| INACTIVE_RETRACK_NOT_ALLOWED | 4013 | 400 | Retrack is not allowed. You can only retrack an inactive tracking. |
+| NOTIFICATION_REUQIRED | 4014 | 400 | notification object is required. |
+| ID_INVALID | 4015 | 400 | The value of id is invalid. |
+| RETRACK_ONCE_ALLOWED | 4016 | 400 | Retrack is not allowed. You can only retrack each shipment once. |
+| TRACKING_NUMBER_FORMAT_INVALID | 4017 | 400 | The format of tracking_number is invalid. |
+| API_KEY_INVALID | 401 | 401 | The API key is invalid. |
+| REQUEST_NOT_ALLOWED | 403 | 403 | The request is understood, but it has been refused or access is not allowed. |
+| NOT_FOUND | 404 | 404 | The URI requested is invalid or the resource requested does not exist. |
+| TOO_MANY_REQUEST | 429 | 429 | You have exceeded the API call rate limit. The default limit is 10 requests per second. |
+| INTERNAL_ERROR | 500 502 503 504 | 500 502 503 504 | Something went wrong on AfterShip's end. |
+
+## Endpoints
+
+The AfterShip instance has the following properties which are exactly the same as the API endpoints:
+
+- courier - Get a list of our supported couriers.
+- tracking - Create trackings, update trackings, and get tracking results.
+- estimated-delivery-date - Get estimated delivery date for your order.
+
+
+### /trackings
+
+**POST** /trackings
+
+```python
+import tracking
+from tracking import (
+ auth,
+ exceptions
+)
+
+try:
+ sdk = tracking.Client(
+ tracking.Configuration(
+ api_key="YOUR_API_KEY",
+ api_secret="YOUR_API_SECRET",
+ authentication_type=auth.Aes,
+ )
+ )
+ data = tracking.CreateTrackingRequest()
+ data.tracking_number = ""
+ data.slug = ""
+ result = sdk.tracking.create_tracking(data)
+ print(result)
+except exceptions.InvalidOptionError:
+ pass
+```
+
+**DELETE** /trackings/:id
+
+```python
+sdk.tracking.delete_tracking_by_id("")
+```
+
+**GET** /trackings
+
+```python
+result = sdk.tracking.get_trackings(keyword="1234")
+print(result)
+```
+
+**GET** /trackings/:id
+
+```python
+result = sdk.tracking.get_tracking_by_id("")
+print(result)
+```
+
+**PUT** /trackings/:id
+
+```python
+data = tracking.UpdateTrackingByIdRequest()
+data.note = "test"
+result = sdk.tracking.update_tracking_by_id("", data)
+print(result)
+```
+
+**POST** /trackings/:id/retrack
+
+```python
+result = sdk.tracking.retrack_tracking_by_id("")
+print(result)
+```
+
+**POST** /trackings/:id/mark-as-completed
+
+```python
+data = tracking.MarkTrackingCompletedByIdRequest()
+data.reason = "DELIVERED"
+result = sdk.tracking.mark_tracking_completed_by_id("", data)
+print(result)
+```
+
+### /couriers
+**GET** /couriers
+
+```python
+result = sdk.courier.get_user_couriers()
+print(result)
+```
+
+**GET** /couriers/all
+
+```python
+result = sdk.courier.get_all_couriers()
+print(result)
+```
+
+**POST** /couriers/detect
+
+```python
+data = tracking.DetectCourierRequest()
+data.tracking_number = ""
+result = sdk.courier.detect_courier(data)
+print(result)
+```
+
+### /estimated-delivery-date
+
+**POST** /estimated-delivery-date/predict-batch
+
+```python
+req = tracking.PredictBatchRequest()
+date = tracking.EstimatedDeliveryDateRequest()
+date.slug = ''
+req.estimated_delivery_dates = [date]
+result = sdk.estimated_delivery_date.predict_batch(req)
+print(result)
+```
+
+## Help
+
+If you get stuck, we're here to help:
+
+- [Issue Tracker](https://github.com/AfterShip/tracking-sdk-python/issues) for questions, feature requests, bug reports and general discussion related to this package. Try searching before you create a new issue.
+- Contact AfterShip official support via support@aftership.com
+
+## License
+Copyright (c) 2024 AfterShip
+
+Licensed under the MIT license.
\ No newline at end of file
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 0000000..53bc2a5
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,529 @@
+# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""}
+
+[[package]]
+name = "anyio"
+version = "4.4.0"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
+ {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
+]
+
+[package.dependencies]
+exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
+idna = ">=2.8"
+sniffio = ">=1.1"
+typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""}
+
+[package.extras]
+doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
+test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
+trio = ["trio (>=0.23)"]
+
+[[package]]
+name = "certifi"
+version = "2024.7.4"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
+ {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.2.2"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+ {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "flake8"
+version = "5.0.4"
+description = "the modular source code checker: pep8 pyflakes and co"
+optional = false
+python-versions = ">=3.6.1"
+files = [
+ {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"},
+ {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"},
+]
+
+[package.dependencies]
+mccabe = ">=0.7.0,<0.8.0"
+pycodestyle = ">=2.9.0,<2.10.0"
+pyflakes = ">=2.5.0,<2.6.0"
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.5"
+description = "A minimal low-level HTTP client."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
+ {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
+]
+
+[package.dependencies]
+certifi = "*"
+h11 = ">=0.13,<0.15"
+
+[package.extras]
+asyncio = ["anyio (>=4.0,<5.0)"]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+trio = ["trio (>=0.22.0,<0.26.0)"]
+
+[[package]]
+name = "httpx"
+version = "0.27.0"
+description = "The next generation HTTP client."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
+ {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
+]
+
+[package.dependencies]
+anyio = "*"
+certifi = "*"
+httpcore = "==1.*"
+idna = "*"
+sniffio = "*"
+
+[package.extras]
+brotli = ["brotli", "brotlicffi"]
+cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+
+[[package]]
+name = "idna"
+version = "3.7"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[package]]
+name = "packaging"
+version = "24.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
+ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
+]
+
+[[package]]
+name = "pluggy"
+version = "1.5.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "pycodestyle"
+version = "2.9.1"
+description = "Python style guide checker"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"},
+ {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"},
+]
+
+[[package]]
+name = "pycryptodome"
+version = "3.20.0"
+description = "Cryptographic library for Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"},
+ {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"},
+ {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"},
+ {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"},
+]
+
+[[package]]
+name = "pydantic"
+version = "2.8.2"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"},
+ {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.4.0"
+pydantic-core = "2.20.1"
+typing-extensions = [
+ {version = ">=4.12.2", markers = "python_version >= \"3.13\""},
+ {version = ">=4.6.1", markers = "python_version < \"3.13\""},
+]
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.20.1"
+description = "Core functionality for Pydantic validation and serialization"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"},
+ {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"},
+ {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"},
+ {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"},
+ {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"},
+ {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"},
+ {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"},
+ {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"},
+ {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"},
+ {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"},
+ {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"},
+ {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"},
+ {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"},
+ {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"},
+ {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"},
+ {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"},
+ {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"},
+ {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"},
+ {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"},
+ {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"},
+ {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"},
+ {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "pyflakes"
+version = "2.5.0"
+description = "passive checker of Python programs"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"},
+ {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"},
+]
+
+[[package]]
+name = "pytest"
+version = "8.3.2"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"},
+ {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=1.5,<2"
+tomli = {version = ">=1", markers = "python_version < \"3.11\""}
+
+[package.extras]
+dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "retrying"
+version = "1.3.4"
+description = "Retrying"
+optional = false
+python-versions = "*"
+files = [
+ {file = "retrying-1.3.4-py3-none-any.whl", hash = "sha256:8cc4d43cb8e1125e0ff3344e9de678fefd85db3b750b81b2240dc0183af37b35"},
+ {file = "retrying-1.3.4.tar.gz", hash = "sha256:345da8c5765bd982b1d1915deb9102fd3d1f7ad16bd84a9700b85f64d24e8f3e"},
+]
+
+[package.dependencies]
+six = ">=1.7.0"
+
+[[package]]
+name = "ruff"
+version = "0.4.10"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.4.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c2c4d0859305ac5a16310eec40e4e9a9dec5dcdfbe92697acd99624e8638dac"},
+ {file = "ruff-0.4.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a79489607d1495685cdd911a323a35871abfb7a95d4f98fc6f85e799227ac46e"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1dd1681dfa90a41b8376a61af05cc4dc5ff32c8f14f5fe20dba9ff5deb80cd6"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c75c53bb79d71310dc79fb69eb4902fba804a81f374bc86a9b117a8d077a1784"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18238c80ee3d9100d3535d8eb15a59c4a0753b45cc55f8bf38f38d6a597b9739"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d8f71885bce242da344989cae08e263de29752f094233f932d4f5cfb4ef36a81"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:330421543bd3222cdfec481e8ff3460e8702ed1e58b494cf9d9e4bf90db52b9d"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e9b6fb3a37b772628415b00c4fc892f97954275394ed611056a4b8a2631365e"},
+ {file = "ruff-0.4.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f54c481b39a762d48f64d97351048e842861c6662d63ec599f67d515cb417f6"},
+ {file = "ruff-0.4.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:67fe086b433b965c22de0b4259ddfe6fa541c95bf418499bedb9ad5fb8d1c631"},
+ {file = "ruff-0.4.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:acfaaab59543382085f9eb51f8e87bac26bf96b164839955f244d07125a982ef"},
+ {file = "ruff-0.4.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3cea07079962b2941244191569cf3a05541477286f5cafea638cd3aa94b56815"},
+ {file = "ruff-0.4.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:338a64ef0748f8c3a80d7f05785930f7965d71ca260904a9321d13be24b79695"},
+ {file = "ruff-0.4.10-py3-none-win32.whl", hash = "sha256:ffe3cd2f89cb54561c62e5fa20e8f182c0a444934bf430515a4b422f1ab7b7ca"},
+ {file = "ruff-0.4.10-py3-none-win_amd64.whl", hash = "sha256:67f67cef43c55ffc8cc59e8e0b97e9e60b4837c8f21e8ab5ffd5d66e196e25f7"},
+ {file = "ruff-0.4.10-py3-none-win_arm64.whl", hash = "sha256:dd1fcee327c20addac7916ca4e2653fbbf2e8388d8a6477ce5b4e986b68ae6c0"},
+ {file = "ruff-0.4.10.tar.gz", hash = "sha256:3aa4f2bc388a30d346c56524f7cacca85945ba124945fe489952aadb6b5cd804"},
+]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
+]
+
+[[package]]
+name = "socksio"
+version = "1.0.0"
+description = "Sans-I/O implementation of SOCKS4, SOCKS4A, and SOCKS5."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3"},
+ {file = "socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac"},
+]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.2.2"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
+ {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.8"
+content-hash = "f4dc3863a79f37180dffdb48dfb2dba5a54de46477a55b21b3346051dfc9188a"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..785c184
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,54 @@
+[tool.poetry]
+name = "aftership-tracking-sdk"
+version = "4.0.0"
+description = "The official AfterShip Tracking Python API library"
+authors = ["AfterShip "]
+license = "MIT"
+readme = "README.md"
+keywords = ["aftership", "tracking", "track", "fedex", "ups", "usps", "dhl", "shipping", "fulfillment", "couriers", "carriers", "logistics"]
+
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Topic :: Software Development",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+]
+
+packages = [
+ { include = "tracking" },
+ { include = "*.md" },
+ { include = "LICENSE" },
+]
+
+[tool.poetry.dependencies]
+python = "^3.8"
+pycryptodome = ">= 3.9.0"
+pydantic = ">=2"
+httpx = ">=0.27.0"
+retrying = "^1.3.4"
+typing_extensions = ">=4.7.1"
+urllib3 = "^2.2.2"
+socksio = "^1.0.0"
+
+[tool.poetry.group.dev.dependencies]
+ruff = "^0.4.8"
+pytest = "^8.2.2"
+flake8 = ">=4.0.0"
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"
+
+[tool.ruff]
+target-version = "py311"
+line-length = 100
+
+[tool.ruff.format]
+quote-style = "double"
+indent-style = "space"
+docstring-code-format = true
+docstring-code-line-length = 60
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..5972212
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,8 @@
+[flake8]
+max-line-length=99
+
+[bdist_wheel]
+universal = 0
+
+[metadata]
+license_file = LICENSE
\ No newline at end of file
diff --git a/tracking/__init__.py b/tracking/__init__.py
new file mode 100644
index 0000000..e07ac27
--- /dev/null
+++ b/tracking/__init__.py
@@ -0,0 +1,14 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+# flake8: noqa
+
+from .auth import ApiKey, Aes, Rsa
+from .client import Client
+from .configuration import Configuration
+from . import exceptions
+from .models import *
+
+__version__ = "4.0.0"
diff --git a/tracking/api/__init__.py b/tracking/api/__init__.py
new file mode 100644
index 0000000..44ab4c4
--- /dev/null
+++ b/tracking/api/__init__.py
@@ -0,0 +1,14 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+__all__ = [
+ "CourierApi",
+ "EstimatedDeliveryDateApi",
+ "TrackingApi",
+]
+
+from .courier import CourierApi
+from .estimated_delivery_date import EstimatedDeliveryDateApi
+from .tracking import TrackingApi
diff --git a/tracking/api/courier.py b/tracking/api/courier.py
new file mode 100644
index 0000000..9ff6da3
--- /dev/null
+++ b/tracking/api/courier.py
@@ -0,0 +1,79 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import json
+from typing import Union
+
+
+from tracking.models import (
+ DetectCourierRequest,
+ DetectCourierResponse,
+ GetAllCouriersResponse,
+ GetUserCouriersResponse,
+)
+from tracking.request import ApiClient, validate_params
+
+
+class CourierApi(ApiClient):
+ """CourierApi api implements"""
+
+ @validate_params
+ def detect_courier(
+ self, detect_courier_request: Union[DetectCourierRequest, dict], **kwargs
+ ) -> DetectCourierResponse:
+ """
+ Return a list of matched couriers based on tracking number format and or a list of couriers.
+ :param detect_courier_request:
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = "/tracking/2024-10/couriers/detect"
+
+ body = detect_courier_request
+ if not isinstance(body, dict):
+ body = detect_courier_request.model_dump(exclude_none=True)
+ body = json.dumps(body)
+
+ result = self._request("POST", url=url, body=body, **kwargs)
+ return DetectCourierResponse().from_dict(result)
+
+ @validate_params
+ def get_all_couriers(self, **kwargs) -> GetAllCouriersResponse:
+ """
+ Return a list of all couriers.
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = "/tracking/2024-10/couriers/all"
+
+ result = self._request("GET", url=url, **kwargs)
+ return GetAllCouriersResponse().from_dict(result)
+
+ @validate_params
+ def get_user_couriers(self, **kwargs) -> GetUserCouriersResponse:
+ """
+ Return a list of .
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = "/tracking/2024-10/couriers"
+
+ result = self._request("GET", url=url, **kwargs)
+ return GetUserCouriersResponse().from_dict(result)
diff --git a/tracking/api/estimated_delivery_date.py b/tracking/api/estimated_delivery_date.py
new file mode 100644
index 0000000..0e0c678
--- /dev/null
+++ b/tracking/api/estimated_delivery_date.py
@@ -0,0 +1,43 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import json
+from typing import Union
+
+
+from tracking.models import (
+ PredictBatchRequest,
+ PredictBatchResponse,
+)
+from tracking.request import ApiClient, validate_params
+
+
+class EstimatedDeliveryDateApi(ApiClient):
+ """EstimatedDeliveryDateApi api implements"""
+
+ @validate_params
+ def predict_batch(
+ self, predict_batch_request: Union[PredictBatchRequest, dict], **kwargs
+ ) -> PredictBatchResponse:
+ """
+ > The estimated delivery date is provided by AfterShip, based on its AI-predictive model. You can display the EDD on the product page, cart, and order checkout page. It indicates when a customer will receive the order.You can use to activate this feature.Supported functionalities require:1. One `EstimatedDeliveryDate` object for one prediction result.2. Maximum 5 `EstimatedDeliveryDate` objects are allowed.3. API call will fail if any of the requests `EstimatedDeliveryDate` objects do not meet the specification requirement.
+ :param predict_batch_request:
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = "/tracking/2024-10/estimated-delivery-date/predict-batch"
+
+ body = predict_batch_request
+ if not isinstance(body, dict):
+ body = predict_batch_request.model_dump(exclude_none=True)
+ body = json.dumps(body)
+
+ result = self._request("POST", url=url, body=body, **kwargs)
+ return PredictBatchResponse().from_dict(result)
diff --git a/tracking/api/tracking.py b/tracking/api/tracking.py
new file mode 100644
index 0000000..8d572f9
--- /dev/null
+++ b/tracking/api/tracking.py
@@ -0,0 +1,240 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import json
+from typing import Union, Annotated
+
+from pydantic import Field
+
+from tracking.models import (
+ CreateTrackingRequest,
+ CreateTrackingResponse,
+ DeleteTrackingByIdResponse,
+ GetTrackingByIdResponse,
+ GetTrackingsResponse,
+ MarkTrackingCompletedByIdRequest,
+ MarkTrackingCompletedByIdResponse,
+ RetrackTrackingByIdResponse,
+ UpdateTrackingByIdRequest,
+ UpdateTrackingByIdResponse,
+)
+from tracking.request import ApiClient, validate_params
+
+
+class TrackingApi(ApiClient):
+ """TrackingApi api implements"""
+
+ @validate_params
+ def create_tracking(
+ self, create_tracking_request: Union[CreateTrackingRequest, dict], **kwargs
+ ) -> CreateTrackingResponse:
+ """
+ Create a tracking.
+ :param create_tracking_request:
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = "/tracking/2024-10/trackings"
+
+ body = create_tracking_request
+ if not isinstance(body, dict):
+ body = create_tracking_request.model_dump(exclude_none=True)
+ body = json.dumps(body)
+
+ result = self._request("POST", url=url, body=body, **kwargs)
+ return CreateTrackingResponse().from_dict(result)
+
+ @validate_params
+ def delete_tracking_by_id(
+ self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
+ ) -> DeleteTrackingByIdResponse:
+ """
+ Delete a tracking.
+ :param tracking_id: str. tracking ID.
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = f"/tracking/2024-10/trackings/{tracking_id}"
+
+ result = self._request("DELETE", url=url, **kwargs)
+ return DeleteTrackingByIdResponse().from_dict(result)
+
+ @validate_params
+ def get_tracking_by_id(
+ self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
+ ) -> GetTrackingByIdResponse:
+ """
+ Get tracking results of a single tracking.
+ :param tracking_id: str. tracking ID.
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ query params:
+ **fields**: str. List of fields to include in the response. Use comma for multiple values. Fields to include: `tracking_postal_code`, `tracking_ship_date`, `tracking_account_number`, `tracking_key`, `tracking_origin_country`, `tracking_destination_country`, `tracking_state`, `title`, `order_id`, `tag`, `checkpoints`
+ **lang**: str. Translate checkpoint messages from the carrier’s provided language to the target language. Supported target languages include: - English (en) - French (fr) - French Canadian (fr-CA) - Arabic (ar) - Bulgarian (bg) - Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl) - Estonian (et) - Filipino (tl) - Finnish (fi) - German (de) - Greek (el) - Hebrew (he) - Hindi (hi) - Hungarian (hu) - Indonesian (id) - Italian (it) - Japanese (ja) - Korean (ko) - Latvian (lv) - Lithuanian (lt) - Malay (ms) - Polish (pl) - Portuguese (pt) - Romanian (ro) - Russian (ru) - Serbian (sr) - Slovak (sk) - Slovenian (sl) - Spanish (es) - Swedish (sv) - Thai (th) - Turkish (tr) - Ukrainian (uk) - Vietnamese (vi) - Simplified Chinese (zh-Hans) - Traditional Chinese (zh-Hant) - Norwegian (nb)
+ """
+ url = f"/tracking/2024-10/trackings/{tracking_id}"
+ params_keys = {
+ "fields",
+ "lang",
+ }
+ params = {key: kwargs.pop(key) for key in params_keys if key in kwargs}
+
+ result = self._request("GET", url=url, params=params, **kwargs)
+ return GetTrackingByIdResponse().from_dict(result)
+
+ @validate_params
+ def get_trackings(self, **kwargs) -> GetTrackingsResponse:
+ """
+ Get tracking results of multiple trackings.
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ query params:
+ **cursor**: str. A string representing the cursor value for the current page of results.
+ **limit**: int. Number of trackings each page contain. (Default: 100, Max: 200)
+ **keyword**: str. Search the content of the tracking record fields: `tracking_number`, `title`, `order_id`, `customer_name`, `custom_fields`, `emails`, `smses`
+ **tracking_numbers**: str. Tracking number of shipments. Use comma to separate multiple values (Example: RA123456789US,LE123456789US). Supports up to 50 tracking numbers.
+ **slug**: str. Unique courier code Use comma for multiple values. (Example: dhl,ups,usps)
+ **transit_time**: int. Total delivery time in days.- When the shipment is delivered: Transit time = Delivered date - Picked up date- When the shipment is not delivered: Transit time = Current date - Picked up dateValue as `null` for the shipment without pickup date.
+ **origin**: str. Origin country/region of trackings. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
+ **destination**: str. Destination country/region of trackings. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
+ **tag**: str. Current status of tracking. Values include `Pending`, `InfoReceived`, `InTransit`, `OutForDelivery`, `AttemptFail`, `Delivered`, `AvailableForPickup`, `Exception`, `Expired` (See tag definition)
+ **created_at_min**: str. Start date and time of trackings created. AfterShip only stores data of 120 days.(Defaults: 30 days ago, Example: 2013-03-15T16:41:56+08:00)
+ **created_at_max**: str. End date and time of trackings created.(Defaults: now, Example: 2013-04-15T16:41:56+08:00)
+ **updated_at_min**: str. Start date and time of trackings updated. (Example: 2013-04-15T16:41:56+08:00)
+ **updated_at_max**: str. End date and time of trackings updated. (Example: 2013-04-15T16:41:56+08:00)
+ **fields**: str. List of fields to include in the response. Use comma for multiple values. Available options: `title`, `order_id`, `tag`, `checkpoints`. Example: `title,order_id`
+ **return_to_sender**: str. Select return to sender, the value should be `true` or `false`, with optional comma separated.
+ **courier_destination_country_iso3**: str. Destination country/region of trackings returned by courier. Use ISO Alpha-3 (three letters). Use comma for multiple values. (Example: USA,HKG)
+ **shipment_tags**: str. Tags you added to your shipments to help categorize and filter them easily. Use a comma to separate multiple values (Example: a,b)
+ **order_id**: str. A globally-unique identifier for the order. Use comma for multiple values.(Example: 6845a095a27a4caeb27487806f058add,4845a095a27a4caeb27487806f058abc)
+ """
+ url = "/tracking/2024-10/trackings"
+ params_keys = {
+ "cursor",
+ "limit",
+ "keyword",
+ "tracking_numbers",
+ "slug",
+ "transit_time",
+ "origin",
+ "destination",
+ "tag",
+ "created_at_min",
+ "created_at_max",
+ "updated_at_min",
+ "updated_at_max",
+ "fields",
+ "return_to_sender",
+ "courier_destination_country_iso3",
+ "shipment_tags",
+ "order_id",
+ }
+ params = {key: kwargs.pop(key) for key in params_keys if key in kwargs}
+
+ result = self._request("GET", url=url, params=params, **kwargs)
+ return GetTrackingsResponse().from_dict(
+ {
+ "pagination": result.get("pagination"),
+ "trackings": result.get("trackings"),
+ }
+ )
+
+ @validate_params
+ def mark_tracking_completed_by_id(
+ self,
+ tracking_id: Annotated[str, Field(min_length=1)],
+ mark_tracking_completed_by_id_request: Union[MarkTrackingCompletedByIdRequest, dict],
+ **kwargs,
+ ) -> MarkTrackingCompletedByIdResponse:
+ """
+ Mark a tracking as completed. The tracking won't auto update until retrack it.
+ :param tracking_id: str. tracking id.
+ :param mark_tracking_completed_by_id_request:
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = f"/tracking/2024-10/trackings/{tracking_id}/mark-as-completed"
+
+ body = mark_tracking_completed_by_id_request
+ if not isinstance(body, dict):
+ body = mark_tracking_completed_by_id_request.model_dump(exclude_none=True)
+ body = json.dumps(body)
+
+ result = self._request("POST", url=url, body=body, **kwargs)
+ return MarkTrackingCompletedByIdResponse().from_dict(result)
+
+ @validate_params
+ def retrack_tracking_by_id(
+ self, tracking_id: Annotated[str, Field(min_length=1)], **kwargs
+ ) -> RetrackTrackingByIdResponse:
+ """
+ Retrack an expired tracking. Max 3 times per tracking.
+ :param tracking_id: str. tracking id.
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = f"/tracking/2024-10/trackings/{tracking_id}/retrack"
+
+ result = self._request("POST", url=url, **kwargs)
+ return RetrackTrackingByIdResponse().from_dict(result)
+
+ @validate_params
+ def update_tracking_by_id(
+ self,
+ tracking_id: Annotated[str, Field(min_length=1)],
+ update_tracking_by_id_request: Union[UpdateTrackingByIdRequest, dict],
+ **kwargs,
+ ) -> UpdateTrackingByIdResponse:
+ """
+ Update a tracking.
+ :param tracking_id: str. tracking ID.
+ :param update_tracking_by_id_request:
+ :param kwargs:
+ request options:
+ **headers** (dict): support custom headers.
+ **verify** bool|str|SSLContext: SSL certificates (a.k.a CA bundle) used to
+ verify the identity of requested hosts. Either `True` (default CA bundle),
+ a path to an SSL certificate file, an `ssl.SSLContext`, or `False`
+ (which will disable verification).
+ """
+ url = f"/tracking/2024-10/trackings/{tracking_id}"
+
+ body = update_tracking_by_id_request
+ if not isinstance(body, dict):
+ body = update_tracking_by_id_request.model_dump(exclude_none=True)
+ body = json.dumps(body)
+
+ result = self._request("PUT", url=url, body=body, **kwargs)
+ return UpdateTrackingByIdResponse().from_dict(result)
diff --git a/tracking/auth.py b/tracking/auth.py
new file mode 100644
index 0000000..ab206aa
--- /dev/null
+++ b/tracking/auth.py
@@ -0,0 +1,134 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import base64
+import hashlib
+import urllib.parse
+import hmac
+from typing import Dict
+from datetime import datetime
+from urllib3.util import url
+
+from Crypto.PublicKey import RSA
+from Crypto.Signature import PKCS1_PSS
+from Crypto.Hash import SHA256
+
+ApiKey = "API_KEY"
+Aes = "AES"
+Rsa = "RSA"
+
+
+class Authenticator:
+ def __init__(self, api_key: str, api_secret: str, auth_type: str):
+ self._api_key: str = api_key
+ self._api_secret: str = api_secret
+ self._kind: str = auth_type
+
+ def sign(self, method: str, uri: str, headers: dict, body: str) -> Dict:
+ """
+ The SignString is generated by Method, Uri, Headers, Body from a HTTP(s) request.
+
+ :param method: str - request method.
+ :param uri: str - request URI.
+ :param headers: dict - request headers.
+ :param body: str - request body.
+ """
+ headers["as-api-key"] = self._api_key
+
+ if self._kind == ApiKey:
+ return headers
+
+ if self._kind != ApiKey:
+ headers["date"] = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
+ concat_header = self.canonical_header(headers)
+ concat_rs = self.canonical_resource(uri)
+ request_date = headers.get("date")
+ sign_str = self.sign_str(method, body, request_date, concat_header, concat_rs)
+
+ if self._kind == Aes:
+ headers["as-signature-hmac-sha256"] = self.hmac_signature(
+ sign_str, self._api_secret
+ )
+
+ if self._kind == Rsa:
+ headers["as-signature-rsa-sha256"] = self.rsa_encrypt(sign_str, self._api_secret)
+
+ return headers
+
+ @classmethod
+ def sign_str(
+ cls, method: str, body: str, date: str, concat_header: str, concat_resource: str
+ ) -> str:
+ content_md5 = ""
+ content_type = ""
+
+ if body is not None and body != "":
+ content_type = "application/json"
+ content_md5 = cls.md5_encode(body)
+
+ return "\n".join([method, content_md5, content_type, date, concat_header, concat_resource])
+
+ @classmethod
+ def canonical_header(cls, headers: Dict) -> str:
+ """
+ :param headers: dict.
+
+ To generate the canonicalized_headers:
+
+ 1. Extract all request headers with the as- prefix key. Kindly note that the headers with the as- prefix
+ are not limited to as-api-key, but also include other as- prefixed key such as as-store-id.
+ 2. Convert all the request header key to lowercase (except the header values case),
+ and sort the headers in ASCII code order.
+ 3. Remove leading spaces and trailing spaces from the header key and value.
+ 4. Concatenate each of the header key and value with :, to form a header pair
+ header_pair = header_key + ":" + header_value
+ 5. Concatenate all header pairs with the new line character (ASCII code 10).
+ """
+ if headers is None or len(headers) == 0:
+ return ""
+
+ result = {k.lower(): v.lstrip() for k, v in headers.items() if k.lower().startswith("as-")}
+ result = dict(sorted(result.items()))
+
+ return "\n".join([f"{k}:{v}" for k, v in result.items()])
+
+ @classmethod
+ def canonical_resource(cls, raw_url: str) -> str:
+ """
+ :param raw_url: str - raw request url.
+ Example : https://api.aftership.com/tracking/2024-10/trackings?key2=value2&key1=value1
+
+ :return canonical_url: str - canonical request url.
+ Example :/tracking/2024-10/trackings?key1=value1&key2=value2
+ """
+ u = url.parse_url(raw_url)
+ resource = u.path
+
+ if u.query is not None and u.query != "":
+ query_dict = urllib.parse.parse_qs(u.query)
+ query_dict = {key: value[0] for key, value in query_dict.items()}
+ resource += "?" + urllib.parse.urlencode(query_dict)
+
+ return resource
+
+ @staticmethod
+ def md5_encode(source: str) -> str:
+ return hashlib.md5(source.encode("utf-8")).hexdigest().upper()
+
+ @staticmethod
+ def rsa_encrypt(sign_str: str, api_secret: str) -> str:
+ private_key = RSA.importKey(api_secret.encode("utf-8"))
+ cipher = PKCS1_PSS.new(private_key)
+ h = SHA256.new()
+ h.update(sign_str.encode("utf-8"))
+ signature = cipher.sign(h)
+ return base64.b64encode(signature).decode("utf-8")
+
+ @staticmethod
+ def hmac_signature(sign_str: str, api_secret: str) -> str:
+ signature = hmac.new(
+ bytes(api_secret, "utf-8"), msg=bytes(sign_str, "utf-8"), digestmod=hashlib.sha256
+ ).digest()
+ return base64.b64encode(signature).decode("utf-8")
diff --git a/tracking/client.py b/tracking/client.py
new file mode 100644
index 0000000..1928fc1
--- /dev/null
+++ b/tracking/client.py
@@ -0,0 +1,21 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+__all__ = ["Client"]
+
+from typing import Optional
+
+from .configuration import Configuration
+from .api import TrackingApi, CourierApi, EstimatedDeliveryDateApi
+
+
+class Client:
+ def __init__(self, configuration: Optional[Configuration] = None) -> None:
+ if configuration is None:
+ configuration = Configuration()
+
+ self.tracking = TrackingApi(configuration)
+ self.courier = CourierApi(configuration)
+ self.estimated_delivery_date = EstimatedDeliveryDateApi(configuration)
diff --git a/tracking/configuration.py b/tracking/configuration.py
new file mode 100644
index 0000000..df67dd5
--- /dev/null
+++ b/tracking/configuration.py
@@ -0,0 +1,112 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import os
+
+from typing import Optional
+
+from tracking.auth import ApiKey, Rsa, Aes
+from tracking.exceptions import InvalidApiKeyError, InvalidOptionError, ErrorCodeEnum
+
+_sdkPrefix = "AFTERSHIP_TRACKING_SDK_"
+
+
+def _get_val_from_env_if_need(value, key_suffix, default=None):
+ if value is None:
+ key = f"{_sdkPrefix}{key_suffix}"
+ return os.environ.get(key, default)
+ return value
+
+
+class Configuration:
+ """This class contains various settings of the API client.
+
+ :param domain: str - Base url.
+ :param authentication_type: str - decide your authentication type.
+ :param api_key: str - AS API key(s).
+ :param api_secret: str - AS api secret.
+ :param max_retry: int - retry limit.
+ :param user_agent: user-agent string for AS.
+ :param timeout: int - milliseconds timeout.
+ :param proxy: str - proxy url string.
+ """
+
+ def __init__(
+ self,
+ domain: Optional[str] = None,
+ authentication_type: Optional[str] = None,
+ max_retry: Optional[int] = None,
+ user_agent: Optional[str] = None,
+ api_key: Optional[str] = None,
+ api_secret: Optional[str] = None,
+ proxy: Optional[str] = None,
+ timeout: Optional[int] = None,
+ ) -> None:
+ self.domain = str(
+ _get_val_from_env_if_need(
+ domain, key_suffix="DOMAIN", default="https://api.aftership.com"
+ )
+ )
+
+ self.authentication_type = str(
+ _get_val_from_env_if_need(
+ authentication_type, key_suffix="AUTHENTICATION_TYPE", default=ApiKey
+ )
+ )
+
+ self.max_retry = int(
+ _get_val_from_env_if_need(max_retry, key_suffix="MAX_RETRY", default=2)
+ )
+
+ self.user_agent = (
+ str(_get_val_from_env_if_need(user_agent, key_suffix="USER_AGENT", default="")) or None
+ )
+
+ self.api_key = (
+ str(_get_val_from_env_if_need(api_key, key_suffix="API_KEY", default="")) or None
+ )
+
+ self.api_secret = (
+ str(_get_val_from_env_if_need(api_secret, key_suffix="API_SECRET", default="")) or None
+ )
+
+ self.proxy = str(_get_val_from_env_if_need(proxy, key_suffix="PROXY", default="")) or None
+
+ self.timeout = int(_get_val_from_env_if_need(timeout, key_suffix="TIMEOUT", default=10000))
+
+ self._validate()
+
+ def _validate(self):
+ if self.domain is None or len(self.domain) == 0:
+ raise InvalidOptionError(
+ code=ErrorCodeEnum.INVALID_OPTION, message=f"Invalid option: domain={self.domain}"
+ )
+ if self.authentication_type not in {ApiKey, Rsa, Aes}:
+ raise InvalidOptionError(
+ code=ErrorCodeEnum.INVALID_OPTION,
+ message=f"Invalid option: authentication_type={self.authentication_type}",
+ )
+
+ if self.api_key is None or len(self.api_key) == 0:
+ raise InvalidApiKeyError(code=ErrorCodeEnum.INVALID_API_KEY, message="Invalid API key")
+
+ if self.authentication_type != ApiKey and (
+ self.api_secret is None or len(self.api_secret) == 0
+ ):
+ raise InvalidOptionError(
+ code=ErrorCodeEnum.INVALID_OPTION,
+ message=f"Invalid option: api_secret={self.api_secret}",
+ )
+
+ if self.max_retry > 10 or self.max_retry < 0:
+ raise InvalidOptionError(
+ code=ErrorCodeEnum.INVALID_OPTION,
+ message=f"Invalid option: max_retry={self.max_retry}",
+ )
+
+ if self.timeout <= 0:
+ raise InvalidOptionError(
+ code=ErrorCodeEnum.INVALID_OPTION, message=f"Invalid option: timeout={self.timeout}"
+ )
diff --git a/tracking/exceptions.py b/tracking/exceptions.py
new file mode 100644
index 0000000..b752b65
--- /dev/null
+++ b/tracking/exceptions.py
@@ -0,0 +1,121 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from typing import Optional
+from enum import Enum, unique
+
+
+class ApiException(Exception):
+ """
+ The base exception class for all ApiException
+
+ :param code: Error code enum. Would be described in the following sections.
+ :param status_code: Same as the http status code. Must have a value.
+ :param message: Error returned by the API: same as meta.message, Error not returned by the API: error object default message
+ :param meta_code: Could be null for the error that is not returned by the API,
+ for example, timeout error, network error.
+ :param response_body: response.body, if any.
+ """
+
+ def __init__(
+ self,
+ code: str,
+ message: str,
+ status_code: Optional[int] = None,
+ meta_code: Optional[int] = None,
+ response_body: Optional[str] = None,
+ ) -> None:
+ super(ApiException, self).__init__()
+ self.meta_code = meta_code
+ self.message = message
+ self.code = code
+ self.status_code = status_code
+ self.response_body = response_body
+
+ def __str__(self):
+ return "{}: {}".format(self.__class__.__name__, self.message)
+
+
+class BadRequestError(ApiException):
+ pass
+
+
+class UnauthorizedError(ApiException):
+ pass
+
+
+class ForbiddenError(ApiException):
+ pass
+
+
+class NotFoundError(ApiException):
+ pass
+
+
+class TooManyRequestsError(ApiException):
+ pass
+
+
+class InternalError(ApiException):
+ pass
+
+
+class TimedOutError(ApiException):
+ pass
+
+
+class UnknownError(ApiException):
+ pass
+
+
+class InvalidApiKeyError(BadRequestError):
+ pass
+
+
+class InvalidOptionError(BadRequestError):
+ pass
+
+
+class RateLimitExceedError(TooManyRequestsError):
+ pass
+
+
+@unique
+class ErrorCodeEnum(Enum):
+ """
+ All available additional fields
+
+ allowed enum values
+ """
+
+ INVALID_API_KEY = "INVALID_API_KEY"
+ INVALID_OPTION = "INVALID_OPTION"
+ BAD_REQUEST = "BAD_REQUEST"
+ RATE_LIMIT_EXCEED = "RATE_LIMIT_EXCEED"
+ TIMED_OUT = "TIMED_OUT"
+ UNKNOW_ERROR = "UNKNOW_ERROR"
+
+ INVALID_REQUEST = "INVALID_REQUEST"
+ INVALID_JSON = "INVALID_JSON"
+ TRACKING_ALREADY_EXIST = "TRACKING_ALREADY_EXIST"
+ TRACKING_DOES_NOT_EXIST = "TRACKING_DOES_NOT_EXIST"
+ TRACKING_NUMBER_INVALID = "TRACKING_NUMBER_INVALID"
+ TRACKING_REQUIRED = "TRACKING_REQUIRED"
+ TRACKING_NUMBER_REQUIRED = "TRACKING_NUMBER_REQUIRED"
+ VALUE_INVALID = "VALUE_INVALID"
+ VALUE_REQUIRED = "VALUE_REQUIRED"
+ SLUG_INVALID = "SLUG_INVALID"
+ MISSING_OR_INVALID_REQUIRED_FIELD = "MISSING_OR_INVALID_REQUIRED_FIELD"
+ BAD_COURIER = "BAD_COURIER"
+ INACTIVE_RETRACK_NOT_ALLOWED = "INACTIVE_RETRACK_NOT_ALLOWED"
+ NOTIFICATION_REUQIRED = "NOTIFICATION_REUQIRED"
+ ID_INVALID = "ID_INVALID"
+ RETRACK_ONCE_ALLOWED = "RETRACK_ONCE_ALLOWED"
+ TRACKING_NUMBER_FORMAT_INVALID = "TRACKING_NUMBER_FORMAT_INVALID"
+ API_KEY_INVALID = "API_KEY_INVALID"
+ REQUEST_NOT_ALLOWED = "REQUEST_NOT_ALLOWED"
+ NOT_FOUND = "NOT_FOUND"
+ TOO_MANY_REQUEST = "TOO_MANY_REQUEST"
+ INTERNAL_ERROR = "INTERNAL_ERROR"
diff --git a/tracking/models/__init__.py b/tracking/models/__init__.py
new file mode 100644
index 0000000..5ecc2fe
--- /dev/null
+++ b/tracking/models/__init__.py
@@ -0,0 +1,306 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+__all__ = [
+ "AdditionalFieldsV1",
+ "AftershipEstimatedDeliveryDateCreateTrackingResponse",
+ "AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse",
+ "AftershipEstimatedDeliveryDateGetTrackingByIdResponse",
+ "AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse",
+ "AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse",
+ "AftershipEstimatedDeliveryDateTracking",
+ "AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse",
+ "CarbonEmissionsCreateTrackingResponse",
+ "CarbonEmissionsDeleteTrackingByIdResponse",
+ "CarbonEmissionsGetTrackingByIdResponse",
+ "CarbonEmissionsMarkTrackingCompletedByIdResponse",
+ "CarbonEmissionsRetrackTrackingByIdResponse",
+ "CarbonEmissionsTracking",
+ "CarbonEmissionsUpdateTrackingByIdResponse",
+ "Checkpoint",
+ "CoordinateCheckpoint",
+ "Courier",
+ "CourierEstimatedDeliveryDateCreateTrackingResponse",
+ "CourierEstimatedDeliveryDateDeleteTrackingByIdResponse",
+ "CourierEstimatedDeliveryDateGetTrackingByIdResponse",
+ "CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse",
+ "CourierEstimatedDeliveryDateRetrackTrackingByIdResponse",
+ "CourierEstimatedDeliveryDateTracking",
+ "CourierEstimatedDeliveryDateUpdateTrackingByIdResponse",
+ "CourierResponseV1",
+ "CreateTrackingRequest",
+ "CreateTrackingResponse",
+ "CustomEstimatedDeliveryDateCreateTrackingResponse",
+ "CustomEstimatedDeliveryDateDeleteTrackingByIdResponse",
+ "CustomEstimatedDeliveryDateGetTrackingByIdResponse",
+ "CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse",
+ "CustomEstimatedDeliveryDateRetrackTrackingByIdResponse",
+ "CustomEstimatedDeliveryDateTracking",
+ "CustomEstimatedDeliveryDateUpdateTrackingByIdResponse",
+ "DataCourierResponseV1",
+ "DataTrackingResponseGetMultipleV1",
+ "DeleteTrackingByIdResponse",
+ "DestinationAddressEstimatedDeliveryDateRequest",
+ "DestinationAddressEstimatedDeliveryDateResponse",
+ "DetectCourierRequest",
+ "DetectCourierResponse",
+ "EstimatedDeliveryDateRequest",
+ "EstimatedDeliveryDateResponse",
+ "EstimatedPickupEstimatedDeliveryDateRequest",
+ "EstimatedPickupEstimatedDeliveryDateResponse",
+ "EventsCheckpoint",
+ "FirstEstimatedDeliveryCreateTrackingResponse",
+ "FirstEstimatedDeliveryDeleteTrackingByIdResponse",
+ "FirstEstimatedDeliveryGetTrackingByIdResponse",
+ "FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse",
+ "FirstEstimatedDeliveryRetrackTrackingByIdResponse",
+ "FirstEstimatedDeliveryTracking",
+ "FirstEstimatedDeliveryUpdateTrackingByIdResponse",
+ "GetAllCouriersResponse",
+ "GetTrackingByIdResponse",
+ "GetTrackingsResponse",
+ "GetUserCouriersResponse",
+ "LatestEstimatedDeliveryCreateTrackingResponse",
+ "LatestEstimatedDeliveryDeleteTrackingByIdResponse",
+ "LatestEstimatedDeliveryGetTrackingByIdResponse",
+ "LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse",
+ "LatestEstimatedDeliveryRetrackTrackingByIdResponse",
+ "LatestEstimatedDeliveryTracking",
+ "LatestEstimatedDeliveryUpdateTrackingByIdResponse",
+ "MarkTrackingCompletedByIdRequest",
+ "MarkTrackingCompletedByIdResponse",
+ "MetaV1",
+ "NextCouriersCreateTrackingRequest",
+ "NextCouriersCreateTrackingResponse",
+ "NextCouriersDeleteTrackingByIdResponse",
+ "NextCouriersGetTrackingByIdResponse",
+ "NextCouriersMarkTrackingCompletedByIdResponse",
+ "NextCouriersRetrackTrackingByIdResponse",
+ "NextCouriersTracking",
+ "NextCouriersUpdateTrackingByIdResponse",
+ "OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest",
+ "OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse",
+ "OriginAddressEstimatedDeliveryDateRequest",
+ "OriginAddressEstimatedDeliveryDateResponse",
+ "Pagination",
+ "PaginationDataTrackingResponseGetMultipleV1",
+ "PaginationGetTrackingsResponse",
+ "PredictBatchRequest",
+ "PredictBatchResponse",
+ "ReasonEventsCheckpoint",
+ "RetrackTrackingByIdResponse",
+ "ShipmentWeightCreateTrackingResponse",
+ "ShipmentWeightDeleteTrackingByIdResponse",
+ "ShipmentWeightGetTrackingByIdResponse",
+ "ShipmentWeightMarkTrackingCompletedByIdResponse",
+ "ShipmentWeightRetrackTrackingByIdResponse",
+ "ShipmentWeightTracking",
+ "ShipmentWeightUpdateTrackingByIdResponse",
+ "SlugGroupV1",
+ "TagV1",
+ "Tracking",
+ "TrackingResponseGetMultipleV1",
+ "TrackingResponseV1",
+ "UpdateTrackingByIdRequest",
+ "UpdateTrackingByIdResponse",
+ "WeightEstimatedDeliveryDateRequest",
+ "WeightEstimatedDeliveryDateResponse",
+]
+
+from .additional_fields_v1 import AdditionalFieldsV1
+from .aftership_estimated_delivery_date_create_tracking_response import (
+ AftershipEstimatedDeliveryDateCreateTrackingResponse,
+)
+from .aftership_estimated_delivery_date_delete_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from .aftership_estimated_delivery_date_get_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from .aftership_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from .aftership_estimated_delivery_date_retrack_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from .aftership_estimated_delivery_date_tracking import AftershipEstimatedDeliveryDateTracking
+from .aftership_estimated_delivery_date_update_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from .carbon_emissions_create_tracking_response import CarbonEmissionsCreateTrackingResponse
+from .carbon_emissions_delete_tracking_by_id_response import (
+ CarbonEmissionsDeleteTrackingByIdResponse,
+)
+from .carbon_emissions_get_tracking_by_id_response import CarbonEmissionsGetTrackingByIdResponse
+from .carbon_emissions_mark_tracking_completed_by_id_response import (
+ CarbonEmissionsMarkTrackingCompletedByIdResponse,
+)
+from .carbon_emissions_retrack_tracking_by_id_response import (
+ CarbonEmissionsRetrackTrackingByIdResponse,
+)
+from .carbon_emissions_tracking import CarbonEmissionsTracking
+from .carbon_emissions_update_tracking_by_id_response import (
+ CarbonEmissionsUpdateTrackingByIdResponse,
+)
+from .checkpoint import Checkpoint
+from .coordinate_checkpoint import CoordinateCheckpoint
+from .courier import Courier
+from .courier_estimated_delivery_date_create_tracking_response import (
+ CourierEstimatedDeliveryDateCreateTrackingResponse,
+)
+from .courier_estimated_delivery_date_delete_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from .courier_estimated_delivery_date_get_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from .courier_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from .courier_estimated_delivery_date_retrack_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from .courier_estimated_delivery_date_tracking import CourierEstimatedDeliveryDateTracking
+from .courier_estimated_delivery_date_update_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from .courier_response_v1 import CourierResponseV1
+from .create_tracking_request import CreateTrackingRequest
+from .create_tracking_response import CreateTrackingResponse
+from .custom_estimated_delivery_date_create_tracking_response import (
+ CustomEstimatedDeliveryDateCreateTrackingResponse,
+)
+from .custom_estimated_delivery_date_delete_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from .custom_estimated_delivery_date_get_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from .custom_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from .custom_estimated_delivery_date_retrack_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from .custom_estimated_delivery_date_tracking import CustomEstimatedDeliveryDateTracking
+from .custom_estimated_delivery_date_update_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from .data_courier_response_v1 import DataCourierResponseV1
+from .data_tracking_response_get_multiple_v1 import DataTrackingResponseGetMultipleV1
+from .delete_tracking_by_id_response import DeleteTrackingByIdResponse
+from .destination_address_estimated_delivery_date_request import (
+ DestinationAddressEstimatedDeliveryDateRequest,
+)
+from .destination_address_estimated_delivery_date_response import (
+ DestinationAddressEstimatedDeliveryDateResponse,
+)
+from .detect_courier_request import DetectCourierRequest
+from .detect_courier_response import DetectCourierResponse
+from .estimated_delivery_date_request import EstimatedDeliveryDateRequest
+from .estimated_delivery_date_response import EstimatedDeliveryDateResponse
+from .estimated_pickup_estimated_delivery_date_request import (
+ EstimatedPickupEstimatedDeliveryDateRequest,
+)
+from .estimated_pickup_estimated_delivery_date_response import (
+ EstimatedPickupEstimatedDeliveryDateResponse,
+)
+from .events_checkpoint import EventsCheckpoint
+from .first_estimated_delivery_create_tracking_response import (
+ FirstEstimatedDeliveryCreateTrackingResponse,
+)
+from .first_estimated_delivery_delete_tracking_by_id_response import (
+ FirstEstimatedDeliveryDeleteTrackingByIdResponse,
+)
+from .first_estimated_delivery_get_tracking_by_id_response import (
+ FirstEstimatedDeliveryGetTrackingByIdResponse,
+)
+from .first_estimated_delivery_mark_tracking_completed_by_id_response import (
+ FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse,
+)
+from .first_estimated_delivery_retrack_tracking_by_id_response import (
+ FirstEstimatedDeliveryRetrackTrackingByIdResponse,
+)
+from .first_estimated_delivery_tracking import FirstEstimatedDeliveryTracking
+from .first_estimated_delivery_update_tracking_by_id_response import (
+ FirstEstimatedDeliveryUpdateTrackingByIdResponse,
+)
+from .get_all_couriers_response import GetAllCouriersResponse
+from .get_tracking_by_id_response import GetTrackingByIdResponse
+from .get_trackings_response import GetTrackingsResponse
+from .get_user_couriers_response import GetUserCouriersResponse
+from .latest_estimated_delivery_create_tracking_response import (
+ LatestEstimatedDeliveryCreateTrackingResponse,
+)
+from .latest_estimated_delivery_delete_tracking_by_id_response import (
+ LatestEstimatedDeliveryDeleteTrackingByIdResponse,
+)
+from .latest_estimated_delivery_get_tracking_by_id_response import (
+ LatestEstimatedDeliveryGetTrackingByIdResponse,
+)
+from .latest_estimated_delivery_mark_tracking_completed_by_id_response import (
+ LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse,
+)
+from .latest_estimated_delivery_retrack_tracking_by_id_response import (
+ LatestEstimatedDeliveryRetrackTrackingByIdResponse,
+)
+from .latest_estimated_delivery_tracking import LatestEstimatedDeliveryTracking
+from .latest_estimated_delivery_update_tracking_by_id_response import (
+ LatestEstimatedDeliveryUpdateTrackingByIdResponse,
+)
+from .mark_tracking_completed_by_id_request import MarkTrackingCompletedByIdRequest
+from .mark_tracking_completed_by_id_response import MarkTrackingCompletedByIdResponse
+from .meta_v1 import MetaV1
+from .next_couriers_create_tracking_request import NextCouriersCreateTrackingRequest
+from .next_couriers_create_tracking_response import NextCouriersCreateTrackingResponse
+from .next_couriers_delete_tracking_by_id_response import NextCouriersDeleteTrackingByIdResponse
+from .next_couriers_get_tracking_by_id_response import NextCouriersGetTrackingByIdResponse
+from .next_couriers_mark_tracking_completed_by_id_response import (
+ NextCouriersMarkTrackingCompletedByIdResponse,
+)
+from .next_couriers_retrack_tracking_by_id_response import NextCouriersRetrackTrackingByIdResponse
+from .next_couriers_tracking import NextCouriersTracking
+from .next_couriers_update_tracking_by_id_response import NextCouriersUpdateTrackingByIdResponse
+from .order_processing_time_estimated_pickup_estimated_delivery_date_request import (
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest,
+)
+from .order_processing_time_estimated_pickup_estimated_delivery_date_response import (
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse,
+)
+from .origin_address_estimated_delivery_date_request import (
+ OriginAddressEstimatedDeliveryDateRequest,
+)
+from .origin_address_estimated_delivery_date_response import (
+ OriginAddressEstimatedDeliveryDateResponse,
+)
+from .pagination import Pagination
+from .pagination_data_tracking_response_get_multiple_v1 import (
+ PaginationDataTrackingResponseGetMultipleV1,
+)
+from .pagination_get_trackings_response import PaginationGetTrackingsResponse
+from .predict_batch_request import PredictBatchRequest
+from .predict_batch_response import PredictBatchResponse
+from .reason_events_checkpoint import ReasonEventsCheckpoint
+from .retrack_tracking_by_id_response import RetrackTrackingByIdResponse
+from .shipment_weight_create_tracking_response import ShipmentWeightCreateTrackingResponse
+from .shipment_weight_delete_tracking_by_id_response import ShipmentWeightDeleteTrackingByIdResponse
+from .shipment_weight_get_tracking_by_id_response import ShipmentWeightGetTrackingByIdResponse
+from .shipment_weight_mark_tracking_completed_by_id_response import (
+ ShipmentWeightMarkTrackingCompletedByIdResponse,
+)
+from .shipment_weight_retrack_tracking_by_id_response import (
+ ShipmentWeightRetrackTrackingByIdResponse,
+)
+from .shipment_weight_tracking import ShipmentWeightTracking
+from .shipment_weight_update_tracking_by_id_response import ShipmentWeightUpdateTrackingByIdResponse
+from .slug_group_v1 import SlugGroupV1
+from .tag_v1 import TagV1
+from .tracking import Tracking
+from .tracking_response_get_multiple_v1 import TrackingResponseGetMultipleV1
+from .tracking_response_v1 import TrackingResponseV1
+from .update_tracking_by_id_request import UpdateTrackingByIdRequest
+from .update_tracking_by_id_response import UpdateTrackingByIdResponse
+from .weight_estimated_delivery_date_request import WeightEstimatedDeliveryDateRequest
+from .weight_estimated_delivery_date_response import WeightEstimatedDeliveryDateResponse
diff --git a/tracking/models/additional_fields_v1.py b/tracking/models/additional_fields_v1.py
new file mode 100644
index 0000000..2008133
--- /dev/null
+++ b/tracking/models/additional_fields_v1.py
@@ -0,0 +1,23 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from enum import Enum, unique
+
+
+@unique
+class AdditionalFieldsV1(Enum):
+ """
+ All available additional fields
+
+ allowed enum values
+ """
+
+ TRACKING_ACCOUNT_NUMBER = "tracking_account_number"
+ TRACKING_POSTAL_CODE = "tracking_postal_code"
+ TRACKING_SHIP_DATE = "tracking_ship_date"
+ TRACKING_KEY = "tracking_key"
+ TRACKING_ORIGIN_COUNTRY = "tracking_origin_country"
+ TRACKING_DESTINATION_COUNTRY = "tracking_destination_country"
+ TRACKING_STATE = "tracking_state"
diff --git a/tracking/models/aftership_estimated_delivery_date_create_tracking_response.py b/tracking/models/aftership_estimated_delivery_date_create_tracking_response.py
new file mode 100644
index 0000000..3bade42
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_create_tracking_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateCreateTrackingResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateCreateTrackingResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_delete_tracking_by_id_response.py b/tracking/models/aftership_estimated_delivery_date_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..9ed259d
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_delete_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_get_tracking_by_id_response.py b/tracking/models/aftership_estimated_delivery_date_get_tracking_by_id_response.py
new file mode 100644
index 0000000..831eb04
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_get_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateGetTrackingByIdResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateGetTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_mark_tracking_completed_by_id_response.py b/tracking/models/aftership_estimated_delivery_date_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..2c0cd31
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_retrack_tracking_by_id_response.py b/tracking/models/aftership_estimated_delivery_date_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..0420e8e
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_retrack_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_tracking.py b/tracking/models/aftership_estimated_delivery_date_tracking.py
new file mode 100644
index 0000000..6e451e1
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_tracking.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateTracking(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateTracking
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/aftership_estimated_delivery_date_update_tracking_by_id_response.py b/tracking/models/aftership_estimated_delivery_date_update_tracking_by_id_response.py
new file mode 100644
index 0000000..e2958d5
--- /dev/null
+++ b/tracking/models/aftership_estimated_delivery_date_update_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse(BaseModel):
+ """
+ AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_create_tracking_response.py b/tracking/models/carbon_emissions_create_tracking_response.py
new file mode 100644
index 0000000..8d71b7d
--- /dev/null
+++ b/tracking/models/carbon_emissions_create_tracking_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsCreateTrackingResponse(BaseModel):
+ """
+ CarbonEmissionsCreateTrackingResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_delete_tracking_by_id_response.py b/tracking/models/carbon_emissions_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..7a7313c
--- /dev/null
+++ b/tracking/models/carbon_emissions_delete_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsDeleteTrackingByIdResponse(BaseModel):
+ """
+ CarbonEmissionsDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_get_tracking_by_id_response.py b/tracking/models/carbon_emissions_get_tracking_by_id_response.py
new file mode 100644
index 0000000..1fa9a26
--- /dev/null
+++ b/tracking/models/carbon_emissions_get_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsGetTrackingByIdResponse(BaseModel):
+ """
+ CarbonEmissionsGetTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_mark_tracking_completed_by_id_response.py b/tracking/models/carbon_emissions_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..b0048d4
--- /dev/null
+++ b/tracking/models/carbon_emissions_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ CarbonEmissionsMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_retrack_tracking_by_id_response.py b/tracking/models/carbon_emissions_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..7a5f8ae
--- /dev/null
+++ b/tracking/models/carbon_emissions_retrack_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsRetrackTrackingByIdResponse(BaseModel):
+ """
+ CarbonEmissionsRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_tracking.py b/tracking/models/carbon_emissions_tracking.py
new file mode 100644
index 0000000..fb98048
--- /dev/null
+++ b/tracking/models/carbon_emissions_tracking.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsTracking(BaseModel):
+ """
+ CarbonEmissionsTracking
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/carbon_emissions_update_tracking_by_id_response.py b/tracking/models/carbon_emissions_update_tracking_by_id_response.py
new file mode 100644
index 0000000..6709557
--- /dev/null
+++ b/tracking/models/carbon_emissions_update_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CarbonEmissionsUpdateTrackingByIdResponse(BaseModel):
+ """
+ CarbonEmissionsUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/checkpoint.py b/tracking/models/checkpoint.py
new file mode 100644
index 0000000..9d6f81a
--- /dev/null
+++ b/tracking/models/checkpoint.py
@@ -0,0 +1,55 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.coordinate_checkpoint import CoordinateCheckpoint
+from tracking.models.tag_v1 import TagV1
+from tracking.models.events_checkpoint import EventsCheckpoint
+
+
+class Checkpoint(BaseModel):
+ """
+ Object describes checkpoint information.
+ """ # noqa: E501
+
+ created_at: Optional[str] = None
+ slug: Optional[str] = None
+ checkpoint_time: Optional[str] = None
+ location: Optional[str] = None
+ city: Optional[str] = None
+ state: Optional[str] = None
+ zip: Optional[str] = None
+ coordinate: Optional[CoordinateCheckpoint] = None
+ country_iso3: Optional[str] = None
+ country_name: Optional[str] = None
+ message: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ raw_tag: Optional[str] = None
+ events: Optional[List[EventsCheckpoint]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/coordinate_checkpoint.py b/tracking/models/coordinate_checkpoint.py
new file mode 100644
index 0000000..b3a8330
--- /dev/null
+++ b/tracking/models/coordinate_checkpoint.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CoordinateCheckpoint(BaseModel):
+ """
+ CoordinateCheckpoint
+ """ # noqa: E501
+
+ latitude: Optional[float] = None
+ longitude: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier.py b/tracking/models/courier.py
new file mode 100644
index 0000000..1113784
--- /dev/null
+++ b/tracking/models/courier.py
@@ -0,0 +1,45 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+
+class Courier(BaseModel):
+ """
+ Courier object
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ name: Optional[str] = None
+ phone: Optional[str] = None
+ other_name: Optional[str] = None
+ web_url: Optional[str] = None
+ required_fields: Optional[List[str]] = None
+ optional_fields: Optional[List[str]] = None
+ default_language: Optional[str] = None
+ support_languages: Optional[List[str]] = None
+ service_from_country_iso3: Optional[List[str]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_create_tracking_response.py b/tracking/models/courier_estimated_delivery_date_create_tracking_response.py
new file mode 100644
index 0000000..464e8cc
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_create_tracking_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateCreateTrackingResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateCreateTrackingResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_delete_tracking_by_id_response.py b/tracking/models/courier_estimated_delivery_date_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..979c62e
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_delete_tracking_by_id_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateDeleteTrackingByIdResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_get_tracking_by_id_response.py b/tracking/models/courier_estimated_delivery_date_get_tracking_by_id_response.py
new file mode 100644
index 0000000..ff14e21
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_get_tracking_by_id_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateGetTrackingByIdResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateGetTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_mark_tracking_completed_by_id_response.py b/tracking/models/courier_estimated_delivery_date_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..a9da337
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_retrack_tracking_by_id_response.py b/tracking/models/courier_estimated_delivery_date_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..f248026
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_retrack_tracking_by_id_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateRetrackTrackingByIdResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_tracking.py b/tracking/models/courier_estimated_delivery_date_tracking.py
new file mode 100644
index 0000000..0021ab3
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_tracking.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateTracking(BaseModel):
+ """
+ CourierEstimatedDeliveryDateTracking
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_estimated_delivery_date_update_tracking_by_id_response.py b/tracking/models/courier_estimated_delivery_date_update_tracking_by_id_response.py
new file mode 100644
index 0000000..e7bfa3b
--- /dev/null
+++ b/tracking/models/courier_estimated_delivery_date_update_tracking_by_id_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CourierEstimatedDeliveryDateUpdateTrackingByIdResponse(BaseModel):
+ """
+ CourierEstimatedDeliveryDateUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ estimated_delivery_date: Optional[str] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/courier_response_v1.py b/tracking/models/courier_response_v1.py
new file mode 100644
index 0000000..c72a40d
--- /dev/null
+++ b/tracking/models/courier_response_v1.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.meta_v1 import MetaV1
+from tracking.models.data_courier_response_v1 import DataCourierResponseV1
+
+
+class CourierResponseV1(BaseModel):
+ """
+ Model of all couriers endpoint response
+ """ # noqa: E501
+
+ meta: Optional[MetaV1] = None
+ data: Optional[DataCourierResponseV1] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/create_tracking_request.py b/tracking/models/create_tracking_request.py
new file mode 100644
index 0000000..fae2338
--- /dev/null
+++ b/tracking/models/create_tracking_request.py
@@ -0,0 +1,79 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.slug_group_v1 import SlugGroupV1
+from tracking.models.next_couriers_create_tracking_request import NextCouriersCreateTrackingRequest
+
+
+class CreateTrackingRequest(BaseModel):
+ """
+ CreateTrackingRequest
+ """ # noqa: E501
+
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ title: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ custom_fields: Optional[Any] = None
+ language: Optional[str] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ emails: Optional[List[str]] = None
+ smses: Optional[List[str]] = None
+ customer_name: Optional[str] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ note: Optional[str] = None
+ slug_group: Optional[SlugGroupV1] = None
+ order_date: Optional[str] = None
+ order_number: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersCreateTrackingRequest]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/create_tracking_response.py b/tracking/models/create_tracking_response.py
new file mode 100644
index 0000000..7465806
--- /dev/null
+++ b/tracking/models/create_tracking_response.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_create_tracking_response import (
+ CourierEstimatedDeliveryDateCreateTrackingResponse,
+)
+from tracking.models.shipment_weight_create_tracking_response import (
+ ShipmentWeightCreateTrackingResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_create_tracking_response import (
+ AftershipEstimatedDeliveryDateCreateTrackingResponse,
+)
+from tracking.models.custom_estimated_delivery_date_create_tracking_response import (
+ CustomEstimatedDeliveryDateCreateTrackingResponse,
+)
+from tracking.models.first_estimated_delivery_create_tracking_response import (
+ FirstEstimatedDeliveryCreateTrackingResponse,
+)
+from tracking.models.latest_estimated_delivery_create_tracking_response import (
+ LatestEstimatedDeliveryCreateTrackingResponse,
+)
+from tracking.models.next_couriers_create_tracking_response import (
+ NextCouriersCreateTrackingResponse,
+)
+from tracking.models.carbon_emissions_create_tracking_response import (
+ CarbonEmissionsCreateTrackingResponse,
+)
+
+
+class CreateTrackingResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateCreateTrackingResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightCreateTrackingResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateCreateTrackingResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[CustomEstimatedDeliveryDateCreateTrackingResponse] = (
+ None
+ )
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryCreateTrackingResponse] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryCreateTrackingResponse] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersCreateTrackingResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsCreateTrackingResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_create_tracking_response.py b/tracking/models/custom_estimated_delivery_date_create_tracking_response.py
new file mode 100644
index 0000000..10bfc19
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_create_tracking_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateCreateTrackingResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateCreateTrackingResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_delete_tracking_by_id_response.py b/tracking/models/custom_estimated_delivery_date_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..17e2ea1
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_delete_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateDeleteTrackingByIdResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_get_tracking_by_id_response.py b/tracking/models/custom_estimated_delivery_date_get_tracking_by_id_response.py
new file mode 100644
index 0000000..948ad09
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_get_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateGetTrackingByIdResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateGetTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_mark_tracking_completed_by_id_response.py b/tracking/models/custom_estimated_delivery_date_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..ac25651
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_retrack_tracking_by_id_response.py b/tracking/models/custom_estimated_delivery_date_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..5480d54
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_retrack_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateRetrackTrackingByIdResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_tracking.py b/tracking/models/custom_estimated_delivery_date_tracking.py
new file mode 100644
index 0000000..3b955e4
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_tracking.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateTracking(BaseModel):
+ """
+ CustomEstimatedDeliveryDateTracking
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/custom_estimated_delivery_date_update_tracking_by_id_response.py b/tracking/models/custom_estimated_delivery_date_update_tracking_by_id_response.py
new file mode 100644
index 0000000..fc7f7cc
--- /dev/null
+++ b/tracking/models/custom_estimated_delivery_date_update_tracking_by_id_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class CustomEstimatedDeliveryDateUpdateTrackingByIdResponse(BaseModel):
+ """
+ CustomEstimatedDeliveryDateUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/data_courier_response_v1.py b/tracking/models/data_courier_response_v1.py
new file mode 100644
index 0000000..5fd3dd4
--- /dev/null
+++ b/tracking/models/data_courier_response_v1.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier import Courier
+
+
+class DataCourierResponseV1(BaseModel):
+ """
+ DataCourierResponseV1
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ couriers: Optional[List[Courier]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/data_tracking_response_get_multiple_v1.py b/tracking/models/data_tracking_response_get_multiple_v1.py
new file mode 100644
index 0000000..4904ab0
--- /dev/null
+++ b/tracking/models/data_tracking_response_get_multiple_v1.py
@@ -0,0 +1,42 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.pagination_data_tracking_response_get_multiple_v1 import (
+ PaginationDataTrackingResponseGetMultipleV1,
+)
+from tracking.models.tracking import Tracking
+
+
+class DataTrackingResponseGetMultipleV1(BaseModel):
+ """
+ DataTrackingResponseGetMultipleV1
+ """ # noqa: E501
+
+ pagination: Optional[PaginationDataTrackingResponseGetMultipleV1] = None
+ trackings: Optional[List[Tracking]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/delete_tracking_by_id_response.py b/tracking/models/delete_tracking_by_id_response.py
new file mode 100644
index 0000000..2ca3c1f
--- /dev/null
+++ b/tracking/models/delete_tracking_by_id_response.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_delete_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from tracking.models.shipment_weight_delete_tracking_by_id_response import (
+ ShipmentWeightDeleteTrackingByIdResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_delete_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from tracking.models.custom_estimated_delivery_date_delete_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateDeleteTrackingByIdResponse,
+)
+from tracking.models.first_estimated_delivery_delete_tracking_by_id_response import (
+ FirstEstimatedDeliveryDeleteTrackingByIdResponse,
+)
+from tracking.models.latest_estimated_delivery_delete_tracking_by_id_response import (
+ LatestEstimatedDeliveryDeleteTrackingByIdResponse,
+)
+from tracking.models.next_couriers_delete_tracking_by_id_response import (
+ NextCouriersDeleteTrackingByIdResponse,
+)
+from tracking.models.carbon_emissions_delete_tracking_by_id_response import (
+ CarbonEmissionsDeleteTrackingByIdResponse,
+)
+
+
+class DeleteTrackingByIdResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateDeleteTrackingByIdResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightDeleteTrackingByIdResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateDeleteTrackingByIdResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[
+ CustomEstimatedDeliveryDateDeleteTrackingByIdResponse
+ ] = None
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryDeleteTrackingByIdResponse] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryDeleteTrackingByIdResponse] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersDeleteTrackingByIdResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsDeleteTrackingByIdResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/destination_address_estimated_delivery_date_request.py b/tracking/models/destination_address_estimated_delivery_date_request.py
new file mode 100644
index 0000000..89c8e09
--- /dev/null
+++ b/tracking/models/destination_address_estimated_delivery_date_request.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class DestinationAddressEstimatedDeliveryDateRequest(BaseModel):
+ """
+ DestinationAddressEstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ country: Optional[str] = None
+ state: Optional[str] = None
+ city: Optional[str] = None
+ postal_code: Optional[str] = None
+ raw_location: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/destination_address_estimated_delivery_date_response.py b/tracking/models/destination_address_estimated_delivery_date_response.py
new file mode 100644
index 0000000..cb4ae16
--- /dev/null
+++ b/tracking/models/destination_address_estimated_delivery_date_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class DestinationAddressEstimatedDeliveryDateResponse(BaseModel):
+ """
+ DestinationAddressEstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ country: Optional[str] = None
+ state: Optional[str] = None
+ city: Optional[str] = None
+ postal_code: Optional[str] = None
+ raw_location: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/detect_courier_request.py b/tracking/models/detect_courier_request.py
new file mode 100644
index 0000000..f58a0cf
--- /dev/null
+++ b/tracking/models/detect_courier_request.py
@@ -0,0 +1,49 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.slug_group_v1 import SlugGroupV1
+
+
+class DetectCourierRequest(BaseModel):
+ """
+ DetectCourierRequest
+ """ # noqa: E501
+
+ tracking_number: Optional[str] = None
+ slug: Optional[List[str]] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_state: Optional[str] = None
+ slug_group: Optional[SlugGroupV1] = None
+ origin_country_iso3: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/detect_courier_response.py b/tracking/models/detect_courier_response.py
new file mode 100644
index 0000000..71005bc
--- /dev/null
+++ b/tracking/models/detect_courier_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier import Courier
+
+
+class DetectCourierResponse(BaseModel):
+ """
+ DetectCourierResponse
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ couriers: Optional[List[Courier]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/estimated_delivery_date_request.py b/tracking/models/estimated_delivery_date_request.py
new file mode 100644
index 0000000..55fd84f
--- /dev/null
+++ b/tracking/models/estimated_delivery_date_request.py
@@ -0,0 +1,56 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.origin_address_estimated_delivery_date_request import (
+ OriginAddressEstimatedDeliveryDateRequest,
+)
+from tracking.models.destination_address_estimated_delivery_date_request import (
+ DestinationAddressEstimatedDeliveryDateRequest,
+)
+from tracking.models.weight_estimated_delivery_date_request import (
+ WeightEstimatedDeliveryDateRequest,
+)
+from tracking.models.estimated_pickup_estimated_delivery_date_request import (
+ EstimatedPickupEstimatedDeliveryDateRequest,
+)
+
+
+class EstimatedDeliveryDateRequest(BaseModel):
+ """
+ EstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ service_type_name: Optional[str] = None
+ origin_address: Optional[OriginAddressEstimatedDeliveryDateRequest] = None
+ destination_address: Optional[DestinationAddressEstimatedDeliveryDateRequest] = None
+ weight: Optional[WeightEstimatedDeliveryDateRequest] = None
+ package_count: Optional[int] = None
+ pickup_time: Optional[str] = None
+ estimated_pickup: Optional[EstimatedPickupEstimatedDeliveryDateRequest] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/estimated_delivery_date_response.py b/tracking/models/estimated_delivery_date_response.py
new file mode 100644
index 0000000..81faf8f
--- /dev/null
+++ b/tracking/models/estimated_delivery_date_response.py
@@ -0,0 +1,61 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.origin_address_estimated_delivery_date_response import (
+ OriginAddressEstimatedDeliveryDateResponse,
+)
+from tracking.models.destination_address_estimated_delivery_date_response import (
+ DestinationAddressEstimatedDeliveryDateResponse,
+)
+from tracking.models.weight_estimated_delivery_date_response import (
+ WeightEstimatedDeliveryDateResponse,
+)
+from tracking.models.estimated_pickup_estimated_delivery_date_response import (
+ EstimatedPickupEstimatedDeliveryDateResponse,
+)
+
+
+class EstimatedDeliveryDateResponse(BaseModel):
+ """
+ EstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ slug: Optional[str] = None
+ service_type_name: Optional[str] = None
+ origin_address: Optional[OriginAddressEstimatedDeliveryDateResponse] = None
+ destination_address: Optional[DestinationAddressEstimatedDeliveryDateResponse] = None
+ weight: Optional[WeightEstimatedDeliveryDateResponse] = None
+ package_count: Optional[int] = None
+ pickup_time: Optional[str] = None
+ estimated_pickup: Optional[EstimatedPickupEstimatedDeliveryDateResponse] = None
+ estimated_delivery_date: Optional[str] = None
+ confidence_code: Optional[float] = None
+ estimated_delivery_date_min: Optional[str] = None
+ estimated_delivery_date_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/estimated_pickup_estimated_delivery_date_request.py b/tracking/models/estimated_pickup_estimated_delivery_date_request.py
new file mode 100644
index 0000000..315c523
--- /dev/null
+++ b/tracking/models/estimated_pickup_estimated_delivery_date_request.py
@@ -0,0 +1,45 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.order_processing_time_estimated_pickup_estimated_delivery_date_request import (
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest,
+)
+
+
+class EstimatedPickupEstimatedDeliveryDateRequest(BaseModel):
+ """
+ EstimatedPickupEstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ order_time: Optional[str] = None
+ order_cutoff_time: Optional[str] = None
+ business_days: Optional[List[int]] = None
+ order_processing_time: Optional[
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest
+ ] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/estimated_pickup_estimated_delivery_date_response.py b/tracking/models/estimated_pickup_estimated_delivery_date_response.py
new file mode 100644
index 0000000..3882fba
--- /dev/null
+++ b/tracking/models/estimated_pickup_estimated_delivery_date_response.py
@@ -0,0 +1,46 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.order_processing_time_estimated_pickup_estimated_delivery_date_response import (
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse,
+)
+
+
+class EstimatedPickupEstimatedDeliveryDateResponse(BaseModel):
+ """
+ EstimatedPickupEstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ order_time: Optional[str] = None
+ order_cutoff_time: Optional[str] = None
+ business_days: Optional[List[int]] = None
+ order_processing_time: Optional[
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse
+ ] = None
+ pickup_time: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/events_checkpoint.py b/tracking/models/events_checkpoint.py
new file mode 100644
index 0000000..dab60e7
--- /dev/null
+++ b/tracking/models/events_checkpoint.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.reason_events_checkpoint import ReasonEventsCheckpoint
+
+
+class EventsCheckpoint(BaseModel):
+ """
+ EventsCheckpoint
+ """ # noqa: E501
+
+ code: Optional[str] = None
+ reason: Optional[ReasonEventsCheckpoint] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_create_tracking_response.py b/tracking/models/first_estimated_delivery_create_tracking_response.py
new file mode 100644
index 0000000..f297493
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_create_tracking_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryCreateTrackingResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryCreateTrackingResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_delete_tracking_by_id_response.py b/tracking/models/first_estimated_delivery_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..fd34db8
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_delete_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryDeleteTrackingByIdResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_get_tracking_by_id_response.py b/tracking/models/first_estimated_delivery_get_tracking_by_id_response.py
new file mode 100644
index 0000000..026516a
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_get_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryGetTrackingByIdResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryGetTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_mark_tracking_completed_by_id_response.py b/tracking/models/first_estimated_delivery_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..ec00ce6
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_retrack_tracking_by_id_response.py b/tracking/models/first_estimated_delivery_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..a611089
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_retrack_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryRetrackTrackingByIdResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_tracking.py b/tracking/models/first_estimated_delivery_tracking.py
new file mode 100644
index 0000000..490234f
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_tracking.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryTracking(BaseModel):
+ """
+ FirstEstimatedDeliveryTracking
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/first_estimated_delivery_update_tracking_by_id_response.py b/tracking/models/first_estimated_delivery_update_tracking_by_id_response.py
new file mode 100644
index 0000000..c046d89
--- /dev/null
+++ b/tracking/models/first_estimated_delivery_update_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class FirstEstimatedDeliveryUpdateTrackingByIdResponse(BaseModel):
+ """
+ FirstEstimatedDeliveryUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/get_all_couriers_response.py b/tracking/models/get_all_couriers_response.py
new file mode 100644
index 0000000..2277b26
--- /dev/null
+++ b/tracking/models/get_all_couriers_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier import Courier
+
+
+class GetAllCouriersResponse(BaseModel):
+ """
+ GetAllCouriersResponse
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ couriers: Optional[List[Courier]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/get_tracking_by_id_response.py b/tracking/models/get_tracking_by_id_response.py
new file mode 100644
index 0000000..b4d519d
--- /dev/null
+++ b/tracking/models/get_tracking_by_id_response.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_get_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from tracking.models.shipment_weight_get_tracking_by_id_response import (
+ ShipmentWeightGetTrackingByIdResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_get_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from tracking.models.custom_estimated_delivery_date_get_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateGetTrackingByIdResponse,
+)
+from tracking.models.first_estimated_delivery_get_tracking_by_id_response import (
+ FirstEstimatedDeliveryGetTrackingByIdResponse,
+)
+from tracking.models.latest_estimated_delivery_get_tracking_by_id_response import (
+ LatestEstimatedDeliveryGetTrackingByIdResponse,
+)
+from tracking.models.next_couriers_get_tracking_by_id_response import (
+ NextCouriersGetTrackingByIdResponse,
+)
+from tracking.models.carbon_emissions_get_tracking_by_id_response import (
+ CarbonEmissionsGetTrackingByIdResponse,
+)
+
+
+class GetTrackingByIdResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateGetTrackingByIdResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightGetTrackingByIdResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateGetTrackingByIdResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[CustomEstimatedDeliveryDateGetTrackingByIdResponse] = (
+ None
+ )
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryGetTrackingByIdResponse] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryGetTrackingByIdResponse] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersGetTrackingByIdResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsGetTrackingByIdResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/get_trackings_response.py b/tracking/models/get_trackings_response.py
new file mode 100644
index 0000000..2d245c0
--- /dev/null
+++ b/tracking/models/get_trackings_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.tracking import Tracking
+from tracking.models.pagination import Pagination
+
+
+class GetTrackingsResponse(BaseModel):
+ """
+ GetTrackingsResponse
+ """ # noqa: E501
+
+ pagination: Optional[Pagination] = None
+ trackings: Optional[List[Tracking]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/get_user_couriers_response.py b/tracking/models/get_user_couriers_response.py
new file mode 100644
index 0000000..110efbe
--- /dev/null
+++ b/tracking/models/get_user_couriers_response.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier import Courier
+
+
+class GetUserCouriersResponse(BaseModel):
+ """
+ GetUserCouriersResponse
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ couriers: Optional[List[Courier]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_create_tracking_response.py b/tracking/models/latest_estimated_delivery_create_tracking_response.py
new file mode 100644
index 0000000..ef87f88
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_create_tracking_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryCreateTrackingResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryCreateTrackingResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_delete_tracking_by_id_response.py b/tracking/models/latest_estimated_delivery_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..34ce107
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_delete_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryDeleteTrackingByIdResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_get_tracking_by_id_response.py b/tracking/models/latest_estimated_delivery_get_tracking_by_id_response.py
new file mode 100644
index 0000000..537ead3
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_get_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryGetTrackingByIdResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryGetTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_mark_tracking_completed_by_id_response.py b/tracking/models/latest_estimated_delivery_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..5eea126
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_retrack_tracking_by_id_response.py b/tracking/models/latest_estimated_delivery_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..f105808
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_retrack_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryRetrackTrackingByIdResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_tracking.py b/tracking/models/latest_estimated_delivery_tracking.py
new file mode 100644
index 0000000..8eaff43
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_tracking.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryTracking(BaseModel):
+ """
+ LatestEstimatedDeliveryTracking
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/latest_estimated_delivery_update_tracking_by_id_response.py b/tracking/models/latest_estimated_delivery_update_tracking_by_id_response.py
new file mode 100644
index 0000000..dacfde6
--- /dev/null
+++ b/tracking/models/latest_estimated_delivery_update_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class LatestEstimatedDeliveryUpdateTrackingByIdResponse(BaseModel):
+ """
+ LatestEstimatedDeliveryUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ type: Optional[str] = None
+ source: Optional[str] = None
+ datetime: Optional[str] = None
+ datetime_min: Optional[str] = None
+ datetime_max: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/mark_tracking_completed_by_id_request.py b/tracking/models/mark_tracking_completed_by_id_request.py
new file mode 100644
index 0000000..c68879d
--- /dev/null
+++ b/tracking/models/mark_tracking_completed_by_id_request.py
@@ -0,0 +1,36 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class MarkTrackingCompletedByIdRequest(BaseModel):
+ """
+ MarkTrackingCompletedByIdRequest
+ """ # noqa: E501
+
+ reason: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/mark_tracking_completed_by_id_response.py b/tracking/models/mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..0dba279
--- /dev/null
+++ b/tracking/models/mark_tracking_completed_by_id_response.py
@@ -0,0 +1,153 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.shipment_weight_mark_tracking_completed_by_id_response import (
+ ShipmentWeightMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.custom_estimated_delivery_date_mark_tracking_completed_by_id_response import (
+ CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.first_estimated_delivery_mark_tracking_completed_by_id_response import (
+ FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.latest_estimated_delivery_mark_tracking_completed_by_id_response import (
+ LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.next_couriers_mark_tracking_completed_by_id_response import (
+ NextCouriersMarkTrackingCompletedByIdResponse,
+)
+from tracking.models.carbon_emissions_mark_tracking_completed_by_id_response import (
+ CarbonEmissionsMarkTrackingCompletedByIdResponse,
+)
+
+
+class MarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightMarkTrackingCompletedByIdResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[
+ CustomEstimatedDeliveryDateMarkTrackingCompletedByIdResponse
+ ] = None
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryMarkTrackingCompletedByIdResponse] = (
+ None
+ )
+ latest_estimated_delivery: Optional[
+ LatestEstimatedDeliveryMarkTrackingCompletedByIdResponse
+ ] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersMarkTrackingCompletedByIdResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsMarkTrackingCompletedByIdResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/meta_v1.py b/tracking/models/meta_v1.py
new file mode 100644
index 0000000..f40b4b1
--- /dev/null
+++ b/tracking/models/meta_v1.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class MetaV1(BaseModel):
+ """
+ Meta data
+ """ # noqa: E501
+
+ code: Optional[int] = None
+ message: Optional[str] = None
+ type: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_create_tracking_request.py b/tracking/models/next_couriers_create_tracking_request.py
new file mode 100644
index 0000000..1c3e797
--- /dev/null
+++ b/tracking/models/next_couriers_create_tracking_request.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersCreateTrackingRequest(BaseModel):
+ """
+ NextCouriersCreateTrackingRequest
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_create_tracking_response.py b/tracking/models/next_couriers_create_tracking_response.py
new file mode 100644
index 0000000..1d33e92
--- /dev/null
+++ b/tracking/models/next_couriers_create_tracking_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersCreateTrackingResponse(BaseModel):
+ """
+ NextCouriersCreateTrackingResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_delete_tracking_by_id_response.py b/tracking/models/next_couriers_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..ac4fb9c
--- /dev/null
+++ b/tracking/models/next_couriers_delete_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersDeleteTrackingByIdResponse(BaseModel):
+ """
+ NextCouriersDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_get_tracking_by_id_response.py b/tracking/models/next_couriers_get_tracking_by_id_response.py
new file mode 100644
index 0000000..6b97929
--- /dev/null
+++ b/tracking/models/next_couriers_get_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersGetTrackingByIdResponse(BaseModel):
+ """
+ NextCouriersGetTrackingByIdResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_mark_tracking_completed_by_id_response.py b/tracking/models/next_couriers_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..d032597
--- /dev/null
+++ b/tracking/models/next_couriers_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ NextCouriersMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_retrack_tracking_by_id_response.py b/tracking/models/next_couriers_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..70283d0
--- /dev/null
+++ b/tracking/models/next_couriers_retrack_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersRetrackTrackingByIdResponse(BaseModel):
+ """
+ NextCouriersRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_tracking.py b/tracking/models/next_couriers_tracking.py
new file mode 100644
index 0000000..82b979d
--- /dev/null
+++ b/tracking/models/next_couriers_tracking.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersTracking(BaseModel):
+ """
+ NextCouriersTracking
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/next_couriers_update_tracking_by_id_response.py b/tracking/models/next_couriers_update_tracking_by_id_response.py
new file mode 100644
index 0000000..11cd4c4
--- /dev/null
+++ b/tracking/models/next_couriers_update_tracking_by_id_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class NextCouriersUpdateTrackingByIdResponse(BaseModel):
+ """
+ NextCouriersUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ slug: Optional[str] = None
+ tracking_number: Optional[str] = None
+ source: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_request.py b/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_request.py
new file mode 100644
index 0000000..e0302bb
--- /dev/null
+++ b/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_request.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest(BaseModel):
+ """
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_response.py b/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_response.py
new file mode 100644
index 0000000..8f81f62
--- /dev/null
+++ b/tracking/models/order_processing_time_estimated_pickup_estimated_delivery_date_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse(BaseModel):
+ """
+ OrderProcessingTimeEstimatedPickupEstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/origin_address_estimated_delivery_date_request.py b/tracking/models/origin_address_estimated_delivery_date_request.py
new file mode 100644
index 0000000..088cd8b
--- /dev/null
+++ b/tracking/models/origin_address_estimated_delivery_date_request.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class OriginAddressEstimatedDeliveryDateRequest(BaseModel):
+ """
+ OriginAddressEstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ country: Optional[str] = None
+ state: Optional[str] = None
+ city: Optional[str] = None
+ postal_code: Optional[str] = None
+ raw_location: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/origin_address_estimated_delivery_date_response.py b/tracking/models/origin_address_estimated_delivery_date_response.py
new file mode 100644
index 0000000..a0ec24c
--- /dev/null
+++ b/tracking/models/origin_address_estimated_delivery_date_response.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class OriginAddressEstimatedDeliveryDateResponse(BaseModel):
+ """
+ OriginAddressEstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ country: Optional[str] = None
+ state: Optional[str] = None
+ city: Optional[str] = None
+ postal_code: Optional[str] = None
+ raw_location: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/pagination.py b/tracking/models/pagination.py
new file mode 100644
index 0000000..f599559
--- /dev/null
+++ b/tracking/models/pagination.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class Pagination(BaseModel):
+ """
+ Pagination
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ next_cursor: Optional[str] = None
+ has_next_page: Optional[bool] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/pagination_data_tracking_response_get_multiple_v1.py b/tracking/models/pagination_data_tracking_response_get_multiple_v1.py
new file mode 100644
index 0000000..4af2175
--- /dev/null
+++ b/tracking/models/pagination_data_tracking_response_get_multiple_v1.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class PaginationDataTrackingResponseGetMultipleV1(BaseModel):
+ """
+ PaginationDataTrackingResponseGetMultipleV1
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ next_cursor: Optional[str] = None
+ has_next_page: Optional[bool] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/pagination_get_trackings_response.py b/tracking/models/pagination_get_trackings_response.py
new file mode 100644
index 0000000..fc6139f
--- /dev/null
+++ b/tracking/models/pagination_get_trackings_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class PaginationGetTrackingsResponse(BaseModel):
+ """
+ PaginationGetTrackingsResponse
+ """ # noqa: E501
+
+ total: Optional[int] = None
+ next_cursor: Optional[str] = None
+ has_next_page: Optional[bool] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/predict_batch_request.py b/tracking/models/predict_batch_request.py
new file mode 100644
index 0000000..2812707
--- /dev/null
+++ b/tracking/models/predict_batch_request.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.estimated_delivery_date_request import EstimatedDeliveryDateRequest
+
+
+class PredictBatchRequest(BaseModel):
+ """
+ PredictBatchRequest
+ """ # noqa: E501
+
+ estimated_delivery_dates: Optional[List[EstimatedDeliveryDateRequest]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/predict_batch_response.py b/tracking/models/predict_batch_response.py
new file mode 100644
index 0000000..a41efa5
--- /dev/null
+++ b/tracking/models/predict_batch_response.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.estimated_delivery_date_response import EstimatedDeliveryDateResponse
+
+
+class PredictBatchResponse(BaseModel):
+ """
+ PredictBatchResponse
+ """ # noqa: E501
+
+ estimated_delivery_dates: Optional[List[EstimatedDeliveryDateResponse]] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/reason_events_checkpoint.py b/tracking/models/reason_events_checkpoint.py
new file mode 100644
index 0000000..b5a799a
--- /dev/null
+++ b/tracking/models/reason_events_checkpoint.py
@@ -0,0 +1,36 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ReasonEventsCheckpoint(BaseModel):
+ """
+ ReasonEventsCheckpoint
+ """ # noqa: E501
+
+ code: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/retrack_tracking_by_id_response.py b/tracking/models/retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..58fbf03
--- /dev/null
+++ b/tracking/models/retrack_tracking_by_id_response.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_retrack_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from tracking.models.shipment_weight_retrack_tracking_by_id_response import (
+ ShipmentWeightRetrackTrackingByIdResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_retrack_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from tracking.models.custom_estimated_delivery_date_retrack_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateRetrackTrackingByIdResponse,
+)
+from tracking.models.first_estimated_delivery_retrack_tracking_by_id_response import (
+ FirstEstimatedDeliveryRetrackTrackingByIdResponse,
+)
+from tracking.models.latest_estimated_delivery_retrack_tracking_by_id_response import (
+ LatestEstimatedDeliveryRetrackTrackingByIdResponse,
+)
+from tracking.models.next_couriers_retrack_tracking_by_id_response import (
+ NextCouriersRetrackTrackingByIdResponse,
+)
+from tracking.models.carbon_emissions_retrack_tracking_by_id_response import (
+ CarbonEmissionsRetrackTrackingByIdResponse,
+)
+
+
+class RetrackTrackingByIdResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateRetrackTrackingByIdResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightRetrackTrackingByIdResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateRetrackTrackingByIdResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[
+ CustomEstimatedDeliveryDateRetrackTrackingByIdResponse
+ ] = None
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryRetrackTrackingByIdResponse] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryRetrackTrackingByIdResponse] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersRetrackTrackingByIdResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsRetrackTrackingByIdResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_create_tracking_response.py b/tracking/models/shipment_weight_create_tracking_response.py
new file mode 100644
index 0000000..0f5b4b4
--- /dev/null
+++ b/tracking/models/shipment_weight_create_tracking_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightCreateTrackingResponse(BaseModel):
+ """
+ ShipmentWeightCreateTrackingResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_delete_tracking_by_id_response.py b/tracking/models/shipment_weight_delete_tracking_by_id_response.py
new file mode 100644
index 0000000..606979a
--- /dev/null
+++ b/tracking/models/shipment_weight_delete_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightDeleteTrackingByIdResponse(BaseModel):
+ """
+ ShipmentWeightDeleteTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_get_tracking_by_id_response.py b/tracking/models/shipment_weight_get_tracking_by_id_response.py
new file mode 100644
index 0000000..e561435
--- /dev/null
+++ b/tracking/models/shipment_weight_get_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightGetTrackingByIdResponse(BaseModel):
+ """
+ ShipmentWeightGetTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_mark_tracking_completed_by_id_response.py b/tracking/models/shipment_weight_mark_tracking_completed_by_id_response.py
new file mode 100644
index 0000000..53a778a
--- /dev/null
+++ b/tracking/models/shipment_weight_mark_tracking_completed_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightMarkTrackingCompletedByIdResponse(BaseModel):
+ """
+ ShipmentWeightMarkTrackingCompletedByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_retrack_tracking_by_id_response.py b/tracking/models/shipment_weight_retrack_tracking_by_id_response.py
new file mode 100644
index 0000000..5bdfaa8
--- /dev/null
+++ b/tracking/models/shipment_weight_retrack_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightRetrackTrackingByIdResponse(BaseModel):
+ """
+ ShipmentWeightRetrackTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_tracking.py b/tracking/models/shipment_weight_tracking.py
new file mode 100644
index 0000000..158daf1
--- /dev/null
+++ b/tracking/models/shipment_weight_tracking.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightTracking(BaseModel):
+ """
+ ShipmentWeightTracking
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/shipment_weight_update_tracking_by_id_response.py b/tracking/models/shipment_weight_update_tracking_by_id_response.py
new file mode 100644
index 0000000..b8da315
--- /dev/null
+++ b/tracking/models/shipment_weight_update_tracking_by_id_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class ShipmentWeightUpdateTrackingByIdResponse(BaseModel):
+ """
+ ShipmentWeightUpdateTrackingByIdResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/slug_group_v1.py b/tracking/models/slug_group_v1.py
new file mode 100644
index 0000000..593d5f6
--- /dev/null
+++ b/tracking/models/slug_group_v1.py
@@ -0,0 +1,28 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from enum import Enum, unique
+
+
+@unique
+class SlugGroupV1(Enum):
+ """
+ Slug group is a group of slugs which belong to same courier. For example, when you inpit "fedex-group" as slug_group, AfterShip will detect the tracking with "fedex-uk", "fedex-fims", and other slugs which belong to "fedex". It cannot be used with slug at the same time. (
+
+ allowed enum values
+ """
+
+ AMAZON_GROUP = "amazon-group"
+ FEDEX_GROUP = "fedex-group"
+ TOLL_GROUP = "toll-group"
+ TAQBIN_GROUP = "taqbin-group"
+ TNT_GROUP = "tnt-group"
+ CJ_GROUP = "cj-group"
+ HERMES_GROUP = "hermes-group"
+ DPD_GROUP = "dpd-group"
+ GLS_GROUP = "gls-group"
+ DHL_GROUP = "dhl-group"
+ FASTWAY_GROUP = "fastway-group"
+ ASENDIA_GROUP = "asendia-group"
diff --git a/tracking/models/tag_v1.py b/tracking/models/tag_v1.py
new file mode 100644
index 0000000..25e0fb6
--- /dev/null
+++ b/tracking/models/tag_v1.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from enum import Enum, unique
+
+
+@unique
+class TagV1(Enum):
+ """
+ Current status of tracking. (
+
+ allowed enum values
+ """
+
+ PENDING = "Pending"
+ INFORECEIVED = "InfoReceived"
+ INTRANSIT = "InTransit"
+ OUTFORDELIVERY = "OutForDelivery"
+ ATTEMPTFAIL = "AttemptFail"
+ DELIVERED = "Delivered"
+ AVAILABLEFORPICKUP = "AvailableForPickup"
+ EXCEPTION = "Exception"
+ EXPIRED = "Expired"
diff --git a/tracking/models/tracking.py b/tracking/models/tracking.py
new file mode 100644
index 0000000..20c1475
--- /dev/null
+++ b/tracking/models/tracking.py
@@ -0,0 +1,133 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_tracking import (
+ CourierEstimatedDeliveryDateTracking,
+)
+from tracking.models.shipment_weight_tracking import ShipmentWeightTracking
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_tracking import (
+ AftershipEstimatedDeliveryDateTracking,
+)
+from tracking.models.custom_estimated_delivery_date_tracking import (
+ CustomEstimatedDeliveryDateTracking,
+)
+from tracking.models.first_estimated_delivery_tracking import FirstEstimatedDeliveryTracking
+from tracking.models.latest_estimated_delivery_tracking import LatestEstimatedDeliveryTracking
+from tracking.models.next_couriers_tracking import NextCouriersTracking
+from tracking.models.carbon_emissions_tracking import CarbonEmissionsTracking
+
+
+class Tracking(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[CourierEstimatedDeliveryDateTracking] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightTracking] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[AftershipEstimatedDeliveryDateTracking] = None
+ custom_estimated_delivery_date: Optional[CustomEstimatedDeliveryDateTracking] = None
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryTracking] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryTracking] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersTracking]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsTracking] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/tracking_response_get_multiple_v1.py b/tracking/models/tracking_response_get_multiple_v1.py
new file mode 100644
index 0000000..642ca1f
--- /dev/null
+++ b/tracking/models/tracking_response_get_multiple_v1.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.meta_v1 import MetaV1
+from tracking.models.data_tracking_response_get_multiple_v1 import DataTrackingResponseGetMultipleV1
+
+
+class TrackingResponseGetMultipleV1(BaseModel):
+ """
+ Tracking response for getting tracking
+ """ # noqa: E501
+
+ meta: Optional[MetaV1] = None
+ data: Optional[DataTrackingResponseGetMultipleV1] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/tracking_response_v1.py b/tracking/models/tracking_response_v1.py
new file mode 100644
index 0000000..95ccd57
--- /dev/null
+++ b/tracking/models/tracking_response_v1.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+from tracking.models.meta_v1 import MetaV1
+from tracking.models.tracking import Tracking
+
+
+class TrackingResponseV1(BaseModel):
+ """
+ Tracking response for returning single tracking
+ """ # noqa: E501
+
+ meta: Optional[MetaV1] = None
+ data: Optional[Tracking] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/update_tracking_by_id_request.py b/tracking/models/update_tracking_by_id_request.py
new file mode 100644
index 0000000..d01ebca
--- /dev/null
+++ b/tracking/models/update_tracking_by_id_request.py
@@ -0,0 +1,71 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+
+class UpdateTrackingByIdRequest(BaseModel):
+ """
+ UpdateTrackingByIdRequest
+ """ # noqa: E501
+
+ smses: Optional[List[str]] = None
+ emails: Optional[List[str]] = None
+ title: Optional[str] = None
+ customer_name: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ custom_fields: Optional[Any] = None
+ note: Optional[str] = None
+ language: Optional[str] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ slug: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ order_number: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/update_tracking_by_id_response.py b/tracking/models/update_tracking_by_id_response.py
new file mode 100644
index 0000000..6482767
--- /dev/null
+++ b/tracking/models/update_tracking_by_id_response.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, List, Optional
+from typing_extensions import Self
+
+from tracking.models.courier_estimated_delivery_date_update_tracking_by_id_response import (
+ CourierEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from tracking.models.shipment_weight_update_tracking_by_id_response import (
+ ShipmentWeightUpdateTrackingByIdResponse,
+)
+from tracking.models.tag_v1 import TagV1
+from tracking.models.checkpoint import Checkpoint
+from tracking.models.aftership_estimated_delivery_date_update_tracking_by_id_response import (
+ AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from tracking.models.custom_estimated_delivery_date_update_tracking_by_id_response import (
+ CustomEstimatedDeliveryDateUpdateTrackingByIdResponse,
+)
+from tracking.models.first_estimated_delivery_update_tracking_by_id_response import (
+ FirstEstimatedDeliveryUpdateTrackingByIdResponse,
+)
+from tracking.models.latest_estimated_delivery_update_tracking_by_id_response import (
+ LatestEstimatedDeliveryUpdateTrackingByIdResponse,
+)
+from tracking.models.next_couriers_update_tracking_by_id_response import (
+ NextCouriersUpdateTrackingByIdResponse,
+)
+from tracking.models.carbon_emissions_update_tracking_by_id_response import (
+ CarbonEmissionsUpdateTrackingByIdResponse,
+)
+
+
+class UpdateTrackingByIdResponse(BaseModel):
+ """
+ Object describes the tracking information.
+ """ # noqa: E501
+
+ id: Optional[str] = None
+ legacy_id: Optional[str] = None
+ created_at: Optional[str] = None
+ updated_at: Optional[str] = None
+ last_updated_at: Optional[str] = None
+ tracking_number: Optional[str] = None
+ slug: Optional[str] = None
+ active: Optional[bool] = None
+ custom_fields: Optional[Any] = None
+ customer_name: Optional[str] = None
+ transit_time: Optional[int] = None
+ origin_country_iso3: Optional[str] = None
+ origin_state: Optional[str] = None
+ origin_city: Optional[str] = None
+ origin_postal_code: Optional[str] = None
+ origin_raw_location: Optional[str] = None
+ destination_country_iso3: Optional[str] = None
+ destination_state: Optional[str] = None
+ destination_city: Optional[str] = None
+ destination_postal_code: Optional[str] = None
+ destination_raw_location: Optional[str] = None
+ courier_destination_country_iso3: Optional[str] = None
+ emails: Optional[List[str]] = None
+ courier_estimated_delivery_date: Optional[
+ CourierEstimatedDeliveryDateUpdateTrackingByIdResponse
+ ] = None
+ note: Optional[str] = None
+ order_id: Optional[str] = None
+ order_id_path: Optional[str] = None
+ order_date: Optional[str] = None
+ shipment_package_count: Optional[float] = None
+ shipment_pickup_date: Optional[str] = None
+ shipment_delivery_date: Optional[str] = None
+ shipment_type: Optional[str] = None
+ shipment_weight: Optional[ShipmentWeightUpdateTrackingByIdResponse] = None
+ signed_by: Optional[str] = None
+ smses: Optional[List[str]] = None
+ source: Optional[str] = None
+ tag: Optional[TagV1] = None
+ subtag: Optional[str] = None
+ subtag_message: Optional[str] = None
+ title: Optional[str] = None
+ tracked_count: Optional[float] = None
+ last_mile_tracking_supported: Optional[bool] = None
+ language: Optional[str] = None
+ unique_token: Optional[str] = None
+ checkpoints: Optional[List[Checkpoint]] = None
+ subscribed_smses: Optional[List[str]] = None
+ subscribed_emails: Optional[List[str]] = None
+ return_to_sender: Optional[bool] = None
+ order_promised_delivery_date: Optional[str] = None
+ delivery_type: Optional[str] = None
+ pickup_location: Optional[str] = None
+ pickup_note: Optional[str] = None
+ courier_tracking_link: Optional[str] = None
+ first_attempted_at: Optional[str] = None
+ courier_redirect_link: Optional[str] = None
+ tracking_account_number: Optional[str] = None
+ tracking_key: Optional[str] = None
+ tracking_ship_date: Optional[str] = None
+ on_time_status: Optional[str] = None
+ on_time_difference: Optional[float] = None
+ order_tags: Optional[List[str]] = None
+ aftership_estimated_delivery_date: Optional[
+ AftershipEstimatedDeliveryDateUpdateTrackingByIdResponse
+ ] = None
+ custom_estimated_delivery_date: Optional[
+ CustomEstimatedDeliveryDateUpdateTrackingByIdResponse
+ ] = None
+ order_number: Optional[str] = None
+ first_estimated_delivery: Optional[FirstEstimatedDeliveryUpdateTrackingByIdResponse] = None
+ latest_estimated_delivery: Optional[LatestEstimatedDeliveryUpdateTrackingByIdResponse] = None
+ shipment_tags: Optional[List[str]] = None
+ courier_connection_id: Optional[str] = None
+ next_couriers: Optional[List[NextCouriersUpdateTrackingByIdResponse]] = None
+ tracking_origin_country: Optional[str] = None
+ tracking_destination_country: Optional[str] = None
+ tracking_postal_code: Optional[str] = None
+ tracking_state: Optional[str] = None
+ carbon_emissions: Optional[CarbonEmissionsUpdateTrackingByIdResponse] = None
+ location_id: Optional[str] = None
+ shipping_method: Optional[str] = None
+ failed_delivery_attempts: Optional[int] = None
+ signature_requirement: Optional[str] = None
+ delivery_location_type: Optional[str] = None
+ aftership_tracking_url: Optional[str] = None
+ aftership_tracking_order_url: Optional[str] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/weight_estimated_delivery_date_request.py b/tracking/models/weight_estimated_delivery_date_request.py
new file mode 100644
index 0000000..f3937f8
--- /dev/null
+++ b/tracking/models/weight_estimated_delivery_date_request.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class WeightEstimatedDeliveryDateRequest(BaseModel):
+ """
+ WeightEstimatedDeliveryDateRequest
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/models/weight_estimated_delivery_date_response.py b/tracking/models/weight_estimated_delivery_date_response.py
new file mode 100644
index 0000000..c84f770
--- /dev/null
+++ b/tracking/models/weight_estimated_delivery_date_response.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+from __future__ import annotations
+import pprint
+
+from pydantic import BaseModel
+from typing import Any, Dict, Optional
+from typing_extensions import Self
+
+
+class WeightEstimatedDeliveryDateResponse(BaseModel):
+ """
+ WeightEstimatedDeliveryDateResponse
+ """ # noqa: E501
+
+ unit: Optional[str] = None
+ value: Optional[float] = None
+
+ def to_str(self, **kwargs) -> str:
+ return pprint.pformat(self.model_dump(**kwargs))
+
+ def to_json(self, **kwargs) -> str:
+ return self.model_dump_json(**kwargs)
+
+ def to_dict(self, **kwargs) -> Dict[str, Any]:
+ return self.model_dump(**kwargs)
+
+ @classmethod
+ def from_json(cls, json_str: str, **kwargs) -> Optional[Self]:
+ return cls.model_validate_json(json_str, **kwargs)
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]], **kwargs) -> Optional[Self]:
+ return cls.model_validate(obj, **kwargs) if isinstance(obj, Dict) else None
diff --git a/tracking/request.py b/tracking/request.py
new file mode 100644
index 0000000..fb0d0a9
--- /dev/null
+++ b/tracking/request.py
@@ -0,0 +1,140 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import random
+from functools import partial, wraps
+from typing import Union, Optional
+from urllib.parse import urljoin
+
+import httpx
+from pydantic import validate_call, ValidationError
+from retrying import retry
+
+from tracking.auth import Authenticator
+from tracking.configuration import Configuration
+from tracking.response import parse_response
+from tracking.exceptions import ApiException, TimedOutError, BadRequestError, ErrorCodeEnum
+
+_default_user_agent = "aftership-sdk-python/4.0.0 (https://www.aftership.com) httpx/0.19.0"
+
+
+def validate_params(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ funcx = validate_call(func)
+ return funcx(*args, **kwargs)
+ except ValidationError as e:
+ raise BadRequestError(code=ErrorCodeEnum.INVALID_OPTION, message=e)
+
+ return wrapper
+
+
+class ApiClient:
+ """Generic API client for OpenAPI client library builds.
+
+ :param configuration: .Configuration object for this client
+ """
+
+ _client = httpx.Client()
+
+ def __init__(self, configuration: Optional[Configuration] = None) -> None:
+ self._config = configuration
+
+ if self._config.proxy is not None:
+ self._client = httpx.Client(proxy=self._config.proxy)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ if self._client is not None:
+ self._client.close()
+
+ def _request(self, method, url, params=None, body=None, **kwargs) -> Union[dict, None]:
+ url = urljoin(self._config.domain, url)
+ user_headers = self._build_headers(body, kwargs.pop("headers", dict()))
+ ssl_ctx = kwargs.pop("verify", None)
+
+ timeout = kwargs.pop("timeout", 0)
+ if timeout <= 0:
+ kwargs["timeout"] = self._config.timeout / 1000.0
+
+ request = self._client.build_request(
+ method=method, url=url, params=params, data=body, headers=user_headers, **kwargs
+ )
+ request.headers = Authenticator(
+ api_key=self._config.api_key,
+ api_secret=self._config.api_secret,
+ auth_type=self._config.authentication_type,
+ ).sign(
+ method=request.method,
+ uri=request.url.raw.raw_path.decode("utf-8"),
+ headers=request.headers,
+ body=body,
+ )
+ return self._send_request_with_retry(ssl_ctx, request)
+
+ def _build_headers(self, body, user_headers) -> dict:
+ _headers = {
+ "aftership-client": _default_user_agent,
+ "user-agent": _default_user_agent,
+ }
+ if self._config.user_agent is not None:
+ _headers["user-agent"] = self._config.user_agent
+
+ if body is not None:
+ _headers["content-type"] = "application/json"
+
+ if "User-Agent" in user_headers:
+ user_headers["user-agent"] = user_headers.pop("User-Agent")
+
+ _headers.update(user_headers)
+ return _headers
+
+ @staticmethod
+ def _retry_if_error(exception):
+ if isinstance(exception, TimedOutError):
+ return True
+
+ if isinstance(exception, ApiException):
+ if exception.status_code >= 500:
+ return True
+ return False
+
+ @staticmethod
+ def _retry_wait(attempts, delay):
+ delay_base = 3000
+ _delay = delay_base * pow(2, attempts - 1)
+ jitter = delay_base * (random.random() - 0.5)
+ return max(1.0, _delay + jitter)
+
+ def _send_request_with_retry(self, ssl_context, request: httpx.Request) -> Union[dict, None]:
+ retry_backoff = partial(
+ retry,
+ wait_func=self._retry_wait,
+ stop_max_attempt_number=self._config.max_retry + 1,
+ retry_on_exception=self._retry_if_error,
+ )
+
+ @retry_backoff()
+ def wrap(ssl_ctx, req):
+ try:
+ if ssl_ctx is None:
+ response = self._client.send(req)
+ else:
+ with httpx.Client(proxy=self._config.proxy, verify=ssl_ctx) as client:
+ response = client.send(req)
+ except httpx.TimeoutException as e:
+ raise TimedOutError(
+ code=ErrorCodeEnum.UNKNOW_ERROR,
+ meta_code=500,
+ status_code=500,
+ message=f"{e.__module__}.{e.__class__.__name__}: {e}",
+ response_body="",
+ )
+ return parse_response(response)
+
+ return wrap(ssl_context, request)
diff --git a/tracking/response.py b/tracking/response.py
new file mode 100644
index 0000000..172fa77
--- /dev/null
+++ b/tracking/response.py
@@ -0,0 +1,94 @@
+# coding: utf-8
+#
+# This code was auto generated by AfterShip SDK Generator.
+# Do not edit the class manually.
+
+import json
+from typing import Union
+
+import httpx
+
+from tracking.exceptions import (
+ ErrorCodeEnum,
+ UnknownError,
+ BadRequestError,
+ UnauthorizedError,
+ ForbiddenError,
+ NotFoundError,
+ InternalError,
+ TooManyRequestsError,
+ TimedOutError,
+)
+
+error_mapping = {
+ "BadRequest": BadRequestError,
+ "Unauthorized": UnauthorizedError,
+ "Forbidden": ForbiddenError,
+ "NotFound": NotFoundError,
+ "TooManyRequests": TooManyRequestsError,
+ "InternalError": InternalError,
+ "TimedOutError": TimedOutError,
+}
+
+_error_meta_code_mapping = {
+ "400": ErrorCodeEnum.INTERNAL_ERROR,
+ "4001": ErrorCodeEnum.INVALID_JSON,
+ "4003": ErrorCodeEnum.TRACKING_ALREADY_EXIST,
+ "4004": ErrorCodeEnum.TRACKING_DOES_NOT_EXIST,
+ "4005": ErrorCodeEnum.TRACKING_NUMBER_INVALID,
+ "4006": ErrorCodeEnum.TRACKING_REQUIRED,
+ "4007": ErrorCodeEnum.TRACKING_NUMBER_REQUIRED,
+ "4008": ErrorCodeEnum.VALUE_INVALID,
+ "4009": ErrorCodeEnum.VALUE_REQUIRED,
+ "4010": ErrorCodeEnum.SLUG_INVALID,
+ "4011": ErrorCodeEnum.MISSING_OR_INVALID_REQUIRED_FIELD,
+ "4012": ErrorCodeEnum.BAD_COURIER,
+ "4013": ErrorCodeEnum.INACTIVE_RETRACK_NOT_ALLOWED,
+ "4014": ErrorCodeEnum.NOTIFICATION_REUQIRED,
+ "4015": ErrorCodeEnum.ID_INVALID,
+ "4016": ErrorCodeEnum.RETRACK_ONCE_ALLOWED,
+ "4017": ErrorCodeEnum.TRACKING_NUMBER_FORMAT_INVALID,
+ "401": ErrorCodeEnum.API_KEY_INVALID,
+ "403": ErrorCodeEnum.REQUEST_NOT_ALLOWED,
+ "404": ErrorCodeEnum.NOT_FOUND,
+ "429": ErrorCodeEnum.TOO_MANY_REQUEST,
+ "500": ErrorCodeEnum.INTERNAL_ERROR,
+ "502": ErrorCodeEnum.INTERNAL_ERROR,
+ "504": ErrorCodeEnum.INTERNAL_ERROR,
+}
+
+
+def get_error_code(meta_code: int) -> str:
+ if _error_meta_code_mapping.get(str(meta_code)):
+ return str(_error_meta_code_mapping[str(meta_code)])
+ return str(ErrorCodeEnum.INTERNAL_ERROR)
+
+
+def parse_response(response: httpx.Response) -> Union[dict, None]:
+ try:
+ json_data = response.json()
+
+ if response.status_code < 300:
+ return json_data["data"]
+
+ error_type = json_data["meta"]["type"]
+ if error_type in error_mapping:
+ error_cls = error_mapping[error_type]
+ else:
+ error_cls = UnknownError
+
+ raise error_cls(
+ code=get_error_code(json_data["meta"]["code"]),
+ meta_code=json_data["meta"]["code"],
+ status_code=response.status_code,
+ message=json_data["meta"]["message"],
+ response_body=response.text,
+ )
+ except (json.JSONDecodeError, KeyError) as e:
+ raise UnknownError(
+ code=ErrorCodeEnum.UNKNOW_ERROR,
+ meta_code=500,
+ status_code=response.status_code,
+ message=f"{e.__module__}.{e.__class__.__name__}: {e}",
+ response_body=response.text,
+ )