sendstack 0.1.2__tar.gz → 0.1.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sendstack
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Sync and async Python SDK for the SendStack email SaaS API.
5
5
  Author: Noria Labs
6
6
  License-Expression: MIT
@@ -123,11 +123,13 @@ decoded payload; on `AsyncSendstack` the same call returns a coroutine you
123
123
 
124
124
  ### Base URL
125
125
 
126
- The SDK defaults to `https://mailer.norialabs.com`, matching the current live
127
- API. Override it when you move to the SendStack domain:
126
+ The SDK defaults to `https://sendstack.norialabs.com/api/v1` (the versioned API
127
+ base). Override `base_url` to point at another environment include the
128
+ `/api/v1` version segment, since resource paths (e.g. `/emails`) are sent
129
+ relative to whatever base you provide:
128
130
 
129
131
  ```python
130
- client = Sendstack(token, base_url="https://sendstack.norialabs.com")
132
+ client = Sendstack(token, base_url="https://staging.norialabs.com/api/v1")
131
133
  ```
132
134
 
133
135
  ## Docs Split
@@ -139,7 +141,7 @@ The SaaS docs remain the canonical source for product/API behavior: account
139
141
  setup, API tokens, domain verification, DNS records, webhook event catalogs,
140
142
  deliverability concepts, provider behavior, dashboard workflows, and the raw
141
143
  HTTP API reference. Current live SaaS docs are at
142
- `https://mailer.norialabs.com/api/docs`.
144
+ `https://sendstack.norialabs.com/api/docs`.
143
145
 
144
146
  ## Auth
145
147
 
@@ -162,7 +164,7 @@ request (sync or async callables both work):
162
164
  from sendstack import BearerAuthStrategy, Sendstack
163
165
 
164
166
  client = Sendstack(
165
- base_url="https://mailer.norialabs.com",
167
+ base_url="https://sendstack.norialabs.com/api/v1",
166
168
  auth=BearerAuthStrategy(token=lambda context: get_fresh_token()),
167
169
  )
168
170
  ```
@@ -96,11 +96,13 @@ decoded payload; on `AsyncSendstack` the same call returns a coroutine you
96
96
 
97
97
  ### Base URL
98
98
 
99
- The SDK defaults to `https://mailer.norialabs.com`, matching the current live
100
- API. Override it when you move to the SendStack domain:
99
+ The SDK defaults to `https://sendstack.norialabs.com/api/v1` (the versioned API
100
+ base). Override `base_url` to point at another environment include the
101
+ `/api/v1` version segment, since resource paths (e.g. `/emails`) are sent
102
+ relative to whatever base you provide:
101
103
 
102
104
  ```python
103
- client = Sendstack(token, base_url="https://sendstack.norialabs.com")
105
+ client = Sendstack(token, base_url="https://staging.norialabs.com/api/v1")
104
106
  ```
105
107
 
106
108
  ## Docs Split
@@ -112,7 +114,7 @@ The SaaS docs remain the canonical source for product/API behavior: account
112
114
  setup, API tokens, domain verification, DNS records, webhook event catalogs,
113
115
  deliverability concepts, provider behavior, dashboard workflows, and the raw
114
116
  HTTP API reference. Current live SaaS docs are at
115
- `https://mailer.norialabs.com/api/docs`.
117
+ `https://sendstack.norialabs.com/api/docs`.
116
118
 
117
119
  ## Auth
118
120
 
@@ -135,7 +137,7 @@ request (sync or async callables both work):
135
137
  from sendstack import BearerAuthStrategy, Sendstack
136
138
 
137
139
  client = Sendstack(
138
- base_url="https://mailer.norialabs.com",
140
+ base_url="https://sendstack.norialabs.com/api/v1",
139
141
  auth=BearerAuthStrategy(token=lambda context: get_fresh_token()),
140
142
  )
141
143
  ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sendstack"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  description = "Sync and async Python SDK for the SendStack email SaaS API."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -20,8 +20,10 @@ from typing import Any, Literal, NotRequired, TypeAlias, TypedDict
20
20
 
21
21
  import httpx
22
22
 
23
- # The live API host. Override via ``base_url`` when SendStack moves domains.
24
- DEFAULT_BASE_URL = "https://mailer.norialabs.com"
23
+ # The versioned API base. Override via ``base_url`` for other environments;
24
+ # include the /api/v1 segment, since resource paths (e.g. /emails) are sent
25
+ # relative to whatever base is configured.
26
+ DEFAULT_BASE_URL = "https://sendstack.norialabs.com/api/v1"
25
27
 
26
28
  # Sentinel distinguishing "no body" from an explicit ``None`` body.
27
29
  UNSET: Any = object()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sendstack
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Sync and async Python SDK for the SendStack email SaaS API.
5
5
  Author: Noria Labs
6
6
  License-Expression: MIT
@@ -123,11 +123,13 @@ decoded payload; on `AsyncSendstack` the same call returns a coroutine you
123
123
 
124
124
  ### Base URL
125
125
 
126
- The SDK defaults to `https://mailer.norialabs.com`, matching the current live
127
- API. Override it when you move to the SendStack domain:
126
+ The SDK defaults to `https://sendstack.norialabs.com/api/v1` (the versioned API
127
+ base). Override `base_url` to point at another environment include the
128
+ `/api/v1` version segment, since resource paths (e.g. `/emails`) are sent
129
+ relative to whatever base you provide:
128
130
 
129
131
  ```python
130
- client = Sendstack(token, base_url="https://sendstack.norialabs.com")
132
+ client = Sendstack(token, base_url="https://staging.norialabs.com/api/v1")
131
133
  ```
132
134
 
133
135
  ## Docs Split
@@ -139,7 +141,7 @@ The SaaS docs remain the canonical source for product/API behavior: account
139
141
  setup, API tokens, domain verification, DNS records, webhook event catalogs,
140
142
  deliverability concepts, provider behavior, dashboard workflows, and the raw
141
143
  HTTP API reference. Current live SaaS docs are at
142
- `https://mailer.norialabs.com/api/docs`.
144
+ `https://sendstack.norialabs.com/api/docs`.
143
145
 
144
146
  ## Auth
145
147
 
@@ -162,7 +164,7 @@ request (sync or async callables both work):
162
164
  from sendstack import BearerAuthStrategy, Sendstack
163
165
 
164
166
  client = Sendstack(
165
- base_url="https://mailer.norialabs.com",
167
+ base_url="https://sendstack.norialabs.com/api/v1",
166
168
  auth=BearerAuthStrategy(token=lambda context: get_fresh_token()),
167
169
  )
168
170
  ```
@@ -131,7 +131,7 @@ def test_send_email_aliases_and_unwraps():
131
131
 
132
132
  assert result == {"id": "m_1", "status": "queued"}
133
133
  request = calls[0]
134
- assert str(request.url) == "https://mailer.norialabs.com/emails"
134
+ assert str(request.url) == "https://sendstack.norialabs.com/api/v1/emails"
135
135
  assert request.method == "POST"
136
136
  assert request.headers["authorization"] == "Bearer tok"
137
137
  assert request.headers["accept"] == "application/json"
@@ -192,10 +192,10 @@ def test_emails_get_events_cancel_requeue():
192
192
  assert client.emails.requeue("m1")["status"] == "queued"
193
193
  finally:
194
194
  http.close()
195
- assert calls[0].url.path == "/emails/m 1" # decoded back by httpx (sent percent-encoded)
196
- assert calls[1].url.path == "/emails/m1/events"
197
- assert calls[2].method == "POST" and calls[2].url.path == "/emails/m1/cancel"
198
- assert calls[3].url.path == "/emails/m1/requeue"
195
+ assert calls[0].url.path == "/api/v1/emails/m 1" # decoded back by httpx (sent percent-encoded)
196
+ assert calls[1].url.path == "/api/v1/emails/m1/events"
197
+ assert calls[2].method == "POST" and calls[2].url.path == "/api/v1/emails/m1/cancel"
198
+ assert calls[3].url.path == "/api/v1/emails/m1/requeue"
199
199
 
200
200
 
201
201
  # --------------------------------------------------------------------------- #
@@ -224,8 +224,8 @@ def test_domains_resource():
224
224
  "provider_id": "p1",
225
225
  "custom_return_path": "bounce",
226
226
  }
227
- assert calls[1].method == "GET" and calls[1].url.path == "/domains"
228
- assert calls[3].url.path == "/domains/d1/verify"
227
+ assert calls[1].method == "GET" and calls[1].url.path == "/api/v1/domains"
228
+ assert calls[3].url.path == "/api/v1/domains/d1/verify"
229
229
 
230
230
 
231
231
  def test_templates_resource_including_delete_returns_none():
@@ -247,7 +247,7 @@ def test_templates_resource_including_delete_returns_none():
247
247
  finally:
248
248
  http.close()
249
249
  assert removed is None
250
- assert calls[3].method == "PATCH" and calls[3].url.path == "/templates/t1"
250
+ assert calls[3].method == "PATCH" and calls[3].url.path == "/api/v1/templates/t1"
251
251
  assert calls[4].method == "DELETE"
252
252
 
253
253
 
@@ -268,8 +268,8 @@ def test_webhooks_resource_event_types_alias():
268
268
  finally:
269
269
  http.close()
270
270
  assert json.loads(calls[0].content) == {"url": "https://e.com", "event_types": ["email.sent"]}
271
- assert calls[0].url.path == "/webhook-endpoints"
272
- assert calls[3].method == "DELETE" and calls[3].url.path == "/webhook-endpoints/wh"
271
+ assert calls[0].url.path == "/api/v1/webhook-endpoints"
272
+ assert calls[3].method == "DELETE" and calls[3].url.path == "/api/v1/webhook-endpoints/wh"
273
273
 
274
274
 
275
275
  def test_webhook_events_retry_alias_attribute():
@@ -280,7 +280,7 @@ def test_webhook_events_retry_alias_attribute():
280
280
  finally:
281
281
  http.close()
282
282
  assert result["webhook_status"] == "queued"
283
- assert calls[0].method == "POST" and calls[0].url.path == "/events/ev_1/retry"
283
+ assert calls[0].method == "POST" and calls[0].url.path == "/api/v1/events/ev_1/retry"
284
284
 
285
285
 
286
286
  def test_suppressions_resource():
@@ -297,8 +297,8 @@ def test_suppressions_resource():
297
297
  client.suppressions.remove("bad@x.com")
298
298
  finally:
299
299
  http.close()
300
- assert calls[0].url.path == "/suppressions"
301
- assert calls[2].method == "DELETE" and calls[2].url.path == "/suppressions/bad@x.com"
300
+ assert calls[0].url.path == "/api/v1/suppressions"
301
+ assert calls[2].method == "DELETE" and calls[2].url.path == "/api/v1/suppressions/bad@x.com"
302
302
 
303
303
 
304
304
  def test_attachments_upload_alias():
@@ -646,7 +646,7 @@ def test_close_owns_vs_injected_and_context_manager():
646
646
  def test_default_base_url_when_unspecified():
647
647
  client = Sendstack("tok")
648
648
  try:
649
- assert client.base_url == "https://mailer.norialabs.com"
649
+ assert client.base_url == "https://sendstack.norialabs.com/api/v1"
650
650
  finally:
651
651
  client.close()
652
652
 
File without changes
File without changes
File without changes