deliveryapi 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build outputs
5
+ dist/
6
+ lib/
7
+ .output/
8
+ .nuxt/
9
+ .astro/
10
+
11
+ # Environment variables (민감정보)
12
+ .env
13
+ .env.*
14
+ !.env.example
15
+
16
+ # Firebase
17
+ .firebase/
18
+ **/serviceAccountKey*.json
19
+ **/serviceAccount*.json
20
+
21
+ # macOS
22
+ .DS_Store
23
+
24
+ # IDE
25
+ .vscode/
26
+ .idea/
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.4
2
+ Name: deliveryapi
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the DeliveryAPI courier tracking platform
5
+ Project-URL: Homepage, https://deliveryapi.co.kr
6
+ Project-URL: Documentation, https://docs.deliveryapi.co.kr
7
+ Author-email: DeliveryAPI <support@deliveryapi.co.kr>
8
+ License: MIT
9
+ Keywords: courier,delivery,korea,sdk,tracking,webhook
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.9
20
+ Requires-Dist: httpx>=0.27.0
21
+ Requires-Dist: typing-extensions>=4.0.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: mypy>=1.9; extra == 'dev'
24
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Requires-Dist: respx>=0.21; extra == 'dev'
27
+ Requires-Dist: ruff>=0.4; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # deliveryapi — Python SDK
31
+
32
+ Official Python SDK for the [DeliveryAPI](https://deliveryapi.co.kr) courier tracking and webhook platform.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install deliveryapi
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from deliveryapi import DeliverySaasClient
44
+
45
+ client = DeliverySaasClient(
46
+ api_key="pk_live_...",
47
+ secret_key="sk_live_...",
48
+ )
49
+
50
+ # Query a single tracking number
51
+ result = client.tracking.get_one("LOTTE", "1234567890")
52
+ item = result["results"][0]
53
+ if item["success"]:
54
+ print(item["data"]["deliveryStatus"]) # e.g. "IN_TRANSIT"
55
+
56
+ # Batch query
57
+ result = client.tracking.get([
58
+ {"courierCode": "LOTTE", "trackingNumber": "1234567890"},
59
+ {"courierCode": "cj", "trackingNumber": "9876543210"},
60
+ ])
61
+ print(result["summary"])
62
+ ```
63
+
64
+ ## Async Support
65
+
66
+ ```python
67
+ import asyncio
68
+ from deliveryapi import AsyncDeliverySaasClient
69
+
70
+ async def main():
71
+ async with AsyncDeliverySaasClient(
72
+ api_key="pk_live_...",
73
+ secret_key="sk_live_...",
74
+ ) as client:
75
+ result = await client.tracking.get_one("LOTTE", "1234567890")
76
+ print(result)
77
+
78
+ asyncio.run(main())
79
+ ```
80
+
81
+ ## Webhook Signature Verification
82
+
83
+ ```python
84
+ from deliveryapi import verify_webhook_signature, WebhookSignatureError
85
+
86
+ # Flask example
87
+ @app.route("/webhook", methods=["POST"])
88
+ def handle_webhook():
89
+ try:
90
+ verify_webhook_signature(
91
+ payload=request.get_data(as_text=True),
92
+ signature=request.headers["X-Webhook-Signature"],
93
+ timestamp=request.headers["X-Webhook-Timestamp"],
94
+ secret="whsec_...",
95
+ )
96
+ except WebhookSignatureError:
97
+ return "Invalid signature", 400
98
+
99
+ event = request.json
100
+ print(event["data"]["currentStatus"])
101
+ return "", 200
102
+ ```
103
+
104
+ ## Error Handling
105
+
106
+ ```python
107
+ from deliveryapi import (
108
+ DeliverySaasClient,
109
+ DeliverySaasError,
110
+ AuthenticationError,
111
+ RateLimitError,
112
+ NotFoundError,
113
+ )
114
+
115
+ client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
116
+
117
+ try:
118
+ result = client.tracking.get_one("LOTTE", "1234567890")
119
+ except AuthenticationError:
120
+ print("Invalid API credentials")
121
+ except RateLimitError:
122
+ print("Rate limit exceeded — slow down requests")
123
+ except NotFoundError:
124
+ print("Resource not found")
125
+ except DeliverySaasError as e:
126
+ print(f"API error {e.status_code}: {e}")
127
+ ```
128
+
129
+ ## Webhook Management
130
+
131
+ ```python
132
+ # Register an endpoint
133
+ endpoint = client.webhooks.create({
134
+ "url": "https://my-server.com/webhook",
135
+ "name": "Production server",
136
+ })
137
+ print(endpoint["id"]) # e.g. "ep_..."
138
+
139
+ # Create a subscription
140
+ sub = client.subscriptions.create({
141
+ "courierCode": "LOTTE",
142
+ "trackingNumber": "1234567890",
143
+ "endpointId": endpoint["id"],
144
+ })
145
+ print(sub["id"]) # e.g. "sub_..."
146
+
147
+ # List and cancel
148
+ subs = client.subscriptions.list(status="active")
149
+ client.subscriptions.cancel(sub["id"])
150
+ ```
151
+
152
+ ## Supported Couriers
153
+
154
+ ```python
155
+ couriers = client.couriers.list()
156
+ for c in couriers["couriers"]:
157
+ print(c["id"], c["displayName"])
158
+ ```
159
+
160
+ ## License
161
+
162
+ MIT
@@ -0,0 +1,133 @@
1
+ # deliveryapi — Python SDK
2
+
3
+ Official Python SDK for the [DeliveryAPI](https://deliveryapi.co.kr) courier tracking and webhook platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install deliveryapi
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from deliveryapi import DeliverySaasClient
15
+
16
+ client = DeliverySaasClient(
17
+ api_key="pk_live_...",
18
+ secret_key="sk_live_...",
19
+ )
20
+
21
+ # Query a single tracking number
22
+ result = client.tracking.get_one("LOTTE", "1234567890")
23
+ item = result["results"][0]
24
+ if item["success"]:
25
+ print(item["data"]["deliveryStatus"]) # e.g. "IN_TRANSIT"
26
+
27
+ # Batch query
28
+ result = client.tracking.get([
29
+ {"courierCode": "LOTTE", "trackingNumber": "1234567890"},
30
+ {"courierCode": "cj", "trackingNumber": "9876543210"},
31
+ ])
32
+ print(result["summary"])
33
+ ```
34
+
35
+ ## Async Support
36
+
37
+ ```python
38
+ import asyncio
39
+ from deliveryapi import AsyncDeliverySaasClient
40
+
41
+ async def main():
42
+ async with AsyncDeliverySaasClient(
43
+ api_key="pk_live_...",
44
+ secret_key="sk_live_...",
45
+ ) as client:
46
+ result = await client.tracking.get_one("LOTTE", "1234567890")
47
+ print(result)
48
+
49
+ asyncio.run(main())
50
+ ```
51
+
52
+ ## Webhook Signature Verification
53
+
54
+ ```python
55
+ from deliveryapi import verify_webhook_signature, WebhookSignatureError
56
+
57
+ # Flask example
58
+ @app.route("/webhook", methods=["POST"])
59
+ def handle_webhook():
60
+ try:
61
+ verify_webhook_signature(
62
+ payload=request.get_data(as_text=True),
63
+ signature=request.headers["X-Webhook-Signature"],
64
+ timestamp=request.headers["X-Webhook-Timestamp"],
65
+ secret="whsec_...",
66
+ )
67
+ except WebhookSignatureError:
68
+ return "Invalid signature", 400
69
+
70
+ event = request.json
71
+ print(event["data"]["currentStatus"])
72
+ return "", 200
73
+ ```
74
+
75
+ ## Error Handling
76
+
77
+ ```python
78
+ from deliveryapi import (
79
+ DeliverySaasClient,
80
+ DeliverySaasError,
81
+ AuthenticationError,
82
+ RateLimitError,
83
+ NotFoundError,
84
+ )
85
+
86
+ client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
87
+
88
+ try:
89
+ result = client.tracking.get_one("LOTTE", "1234567890")
90
+ except AuthenticationError:
91
+ print("Invalid API credentials")
92
+ except RateLimitError:
93
+ print("Rate limit exceeded — slow down requests")
94
+ except NotFoundError:
95
+ print("Resource not found")
96
+ except DeliverySaasError as e:
97
+ print(f"API error {e.status_code}: {e}")
98
+ ```
99
+
100
+ ## Webhook Management
101
+
102
+ ```python
103
+ # Register an endpoint
104
+ endpoint = client.webhooks.create({
105
+ "url": "https://my-server.com/webhook",
106
+ "name": "Production server",
107
+ })
108
+ print(endpoint["id"]) # e.g. "ep_..."
109
+
110
+ # Create a subscription
111
+ sub = client.subscriptions.create({
112
+ "courierCode": "LOTTE",
113
+ "trackingNumber": "1234567890",
114
+ "endpointId": endpoint["id"],
115
+ })
116
+ print(sub["id"]) # e.g. "sub_..."
117
+
118
+ # List and cancel
119
+ subs = client.subscriptions.list(status="active")
120
+ client.subscriptions.cancel(sub["id"])
121
+ ```
122
+
123
+ ## Supported Couriers
124
+
125
+ ```python
126
+ couriers = client.couriers.list()
127
+ for c in couriers["couriers"]:
128
+ print(c["id"], c["displayName"])
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "deliveryapi"
7
+ version = "1.0.0"
8
+ description = "Official Python SDK for the DeliveryAPI courier tracking platform"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ keywords = ["delivery", "courier", "tracking", "webhook", "korea", "sdk"]
13
+ authors = [{ name = "DeliveryAPI", email = "support@deliveryapi.co.kr" }]
14
+ classifiers = [
15
+ "Development Status :: 5 - Production/Stable",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Typing :: Typed",
24
+ ]
25
+
26
+ dependencies = [
27
+ "httpx>=0.27.0",
28
+ "typing_extensions>=4.0.0",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ dev = [
33
+ "pytest>=8.0",
34
+ "pytest-asyncio>=0.23",
35
+ "respx>=0.21",
36
+ "mypy>=1.9",
37
+ "ruff>=0.4",
38
+ ]
39
+
40
+ [project.urls]
41
+ Homepage = "https://deliveryapi.co.kr"
42
+ Documentation = "https://docs.deliveryapi.co.kr"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/deliveryapi"]
46
+
47
+ [tool.ruff]
48
+ src = ["src"]
49
+ target-version = "py39"
50
+
51
+ [tool.ruff.lint]
52
+ select = ["E", "F", "I", "UP"]
53
+
54
+ [tool.mypy]
55
+ strict = true
56
+ mypy_path = "src"
57
+
58
+ [tool.pytest.ini_options]
59
+ asyncio_mode = "auto"
60
+ testpaths = ["tests"]
@@ -0,0 +1,84 @@
1
+ """DeliverySaaS Python SDK.
2
+
3
+ Quick start::
4
+
5
+ from deliveryapi import DeliverySaasClient
6
+
7
+ client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
8
+ result = client.tracking.get_one("LOTTE", "1234567890")
9
+ print(result["results"][0]["data"]["deliveryStatus"])
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from ._client import AsyncDeliverySaasClient, DeliverySaasClient
14
+ from ._exceptions import (
15
+ AuthenticationError,
16
+ DeliverySaasError,
17
+ NotFoundError,
18
+ RateLimitError,
19
+ )
20
+ from ._types import (
21
+ CourierDeliveryStatus,
22
+ CourierInfo,
23
+ CourierListResult,
24
+ SubscriptionCreateInput,
25
+ SubscriptionListResult,
26
+ TrackingCacheInfo,
27
+ TrackingError,
28
+ TrackingErrorCode,
29
+ TrackingItem,
30
+ TrackingProgress,
31
+ TrackingResponse,
32
+ TrackingResult,
33
+ TrackingSummary,
34
+ TrackingSubscription,
35
+ UnifiedTrackingResponse,
36
+ WebhookCreateInput,
37
+ WebhookEndpoint,
38
+ WebhookListResult,
39
+ WebhookPayload,
40
+ WebhookPayloadData,
41
+ WebhookTestResult,
42
+ )
43
+ from ._webhook import WebhookSignatureError, verify_webhook_signature
44
+
45
+ __version__ = "1.0.0"
46
+
47
+ __all__ = [
48
+ # Clients
49
+ "DeliverySaasClient",
50
+ "AsyncDeliverySaasClient",
51
+ # Exceptions
52
+ "DeliverySaasError",
53
+ "AuthenticationError",
54
+ "RateLimitError",
55
+ "NotFoundError",
56
+ # Webhook utils
57
+ "verify_webhook_signature",
58
+ "WebhookSignatureError",
59
+ # Types — tracking
60
+ "CourierDeliveryStatus",
61
+ "TrackingItem",
62
+ "TrackingProgress",
63
+ "TrackingResult",
64
+ "TrackingError",
65
+ "TrackingErrorCode",
66
+ "TrackingCacheInfo",
67
+ "TrackingSummary",
68
+ "TrackingResponse",
69
+ "UnifiedTrackingResponse",
70
+ # Types — couriers
71
+ "CourierInfo",
72
+ "CourierListResult",
73
+ # Types — webhooks
74
+ "WebhookCreateInput",
75
+ "WebhookEndpoint",
76
+ "WebhookListResult",
77
+ "WebhookTestResult",
78
+ "WebhookPayload",
79
+ "WebhookPayloadData",
80
+ # Types — subscriptions
81
+ "SubscriptionCreateInput",
82
+ "TrackingSubscription",
83
+ "SubscriptionListResult",
84
+ ]
@@ -0,0 +1,125 @@
1
+ """Main client classes for the DeliverySaaS API."""
2
+ from __future__ import annotations
3
+
4
+ from ._http import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, AsyncHttpClient, HttpClient
5
+ from .resources.couriers import AsyncCouriersResource, CouriersResource
6
+ from .resources.subscriptions import AsyncSubscriptionsResource, SubscriptionsResource
7
+ from .resources.tracking import AsyncTrackingResource, TrackingResource
8
+ from .resources.webhooks import AsyncWebhooksResource, WebhooksResource
9
+
10
+
11
+ class DeliverySaasClient:
12
+ """Synchronous DeliverySaaS API client.
13
+
14
+ Args:
15
+ api_key: Your API key (``pk_live_...`` or ``pk_test_...``).
16
+ secret_key: Your secret key (``sk_live_...`` or ``sk_test_...``).
17
+ base_url: Override the API base URL (useful for local emulator).
18
+ timeout: HTTP request timeout in seconds (default: 30).
19
+
20
+ Example::
21
+
22
+ from deliveryapi import DeliverySaasClient
23
+
24
+ client = DeliverySaasClient(
25
+ api_key="pk_live_...",
26
+ secret_key="sk_live_...",
27
+ )
28
+
29
+ # List supported couriers
30
+ couriers = client.couriers.list()
31
+
32
+ # Query tracking status
33
+ result = client.tracking.get_one("LOTTE", "1234567890")
34
+
35
+ # Manage webhook endpoints
36
+ endpoint = client.webhooks.create({"url": "https://my.server/webhook"})
37
+
38
+ # Create a subscription
39
+ sub = client.subscriptions.create({
40
+ "courierCode": "LOTTE",
41
+ "trackingNumber": "1234567890",
42
+ "endpointId": endpoint["id"],
43
+ })
44
+
45
+ Context manager::
46
+
47
+ with DeliverySaasClient(api_key="...", secret_key="...") as client:
48
+ result = client.tracking.get_one("LOTTE", "1234567890")
49
+ """
50
+
51
+ def __init__(
52
+ self,
53
+ *,
54
+ api_key: str,
55
+ secret_key: str,
56
+ base_url: str = DEFAULT_BASE_URL,
57
+ timeout: float = DEFAULT_TIMEOUT,
58
+ ) -> None:
59
+ http = HttpClient(api_key, secret_key, base_url, timeout)
60
+ self.tracking = TrackingResource(http)
61
+ self.couriers = CouriersResource(http)
62
+ self.webhooks = WebhooksResource(http)
63
+ self.subscriptions = SubscriptionsResource(http)
64
+ self._http = http
65
+
66
+ def close(self) -> None:
67
+ """Close the underlying HTTP connection pool."""
68
+ self._http.close()
69
+
70
+ def __enter__(self) -> DeliverySaasClient:
71
+ return self
72
+
73
+ def __exit__(self, *args: object) -> None:
74
+ self.close()
75
+
76
+
77
+ class AsyncDeliverySaasClient:
78
+ """Async DeliverySaaS API client (requires asyncio).
79
+
80
+ Args:
81
+ api_key: Your API key (``pk_live_...`` or ``pk_test_...``).
82
+ secret_key: Your secret key (``sk_live_...`` or ``sk_test_...``).
83
+ base_url: Override the API base URL (useful for local emulator).
84
+ timeout: HTTP request timeout in seconds (default: 30).
85
+
86
+ Example::
87
+
88
+ import asyncio
89
+ from deliveryapi import AsyncDeliverySaasClient
90
+
91
+ async def main():
92
+ async with AsyncDeliverySaasClient(
93
+ api_key="pk_live_...",
94
+ secret_key="sk_live_...",
95
+ ) as client:
96
+ result = await client.tracking.get_one("LOTTE", "1234567890")
97
+ print(result)
98
+
99
+ asyncio.run(main())
100
+ """
101
+
102
+ def __init__(
103
+ self,
104
+ *,
105
+ api_key: str,
106
+ secret_key: str,
107
+ base_url: str = DEFAULT_BASE_URL,
108
+ timeout: float = DEFAULT_TIMEOUT,
109
+ ) -> None:
110
+ http = AsyncHttpClient(api_key, secret_key, base_url, timeout)
111
+ self.tracking = AsyncTrackingResource(http)
112
+ self.couriers = AsyncCouriersResource(http)
113
+ self.webhooks = AsyncWebhooksResource(http)
114
+ self.subscriptions = AsyncSubscriptionsResource(http)
115
+ self._http = http
116
+
117
+ async def aclose(self) -> None:
118
+ """Close the underlying async HTTP connection pool."""
119
+ await self._http.aclose()
120
+
121
+ async def __aenter__(self) -> AsyncDeliverySaasClient:
122
+ return self
123
+
124
+ async def __aexit__(self, *args: object) -> None:
125
+ await self.aclose()
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ class DeliverySaasError(Exception):
5
+ """Base exception for all DeliverySaaS API errors."""
6
+
7
+ def __init__(self, message: str, status_code: int, code: str | None = None) -> None:
8
+ super().__init__(message)
9
+ self.status_code = status_code
10
+ self.code = code
11
+
12
+
13
+ class AuthenticationError(DeliverySaasError):
14
+ def __init__(self, message: str = "Invalid API key or secret key") -> None:
15
+ super().__init__(message, 401, "AUTHENTICATION_ERROR")
16
+
17
+
18
+ class RateLimitError(DeliverySaasError):
19
+ def __init__(self, message: str = "Rate limit exceeded") -> None:
20
+ super().__init__(message, 429, "RATE_LIMIT_ERROR")
21
+
22
+
23
+ class NotFoundError(DeliverySaasError):
24
+ def __init__(self, message: str = "Resource not found") -> None:
25
+ super().__init__(message, 404, "NOT_FOUND")