hookbase 2.7.0__tar.gz → 2.9.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.
Files changed (80) hide show
  1. {hookbase-2.7.0 → hookbase-2.9.0}/PKG-INFO +1 -1
  2. hookbase-2.9.0/src/hookbase/_version.py +1 -0
  3. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/destinations.py +6 -3
  4. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/sources.py +20 -4
  5. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_destinations.py +15 -1
  6. hookbase-2.7.0/src/hookbase/_version.py +0 -1
  7. {hookbase-2.7.0 → hookbase-2.9.0}/.github/workflows/python-publish.yml +0 -0
  8. {hookbase-2.7.0 → hookbase-2.9.0}/.gitignore +0 -0
  9. {hookbase-2.7.0 → hookbase-2.9.0}/LICENSE +0 -0
  10. {hookbase-2.7.0 → hookbase-2.9.0}/README.md +0 -0
  11. {hookbase-2.7.0 → hookbase-2.9.0}/examples/async_usage.py +0 -0
  12. {hookbase-2.7.0 → hookbase-2.9.0}/examples/basic_inbound.py +0 -0
  13. {hookbase-2.7.0 → hookbase-2.9.0}/examples/error_handling.py +0 -0
  14. {hookbase-2.7.0 → hookbase-2.9.0}/examples/send_webhooks.py +0 -0
  15. {hookbase-2.7.0 → hookbase-2.9.0}/examples/verify_webhooks.py +0 -0
  16. {hookbase-2.7.0 → hookbase-2.9.0}/pyproject.toml +0 -0
  17. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/__init__.py +0 -0
  18. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/_client.py +0 -0
  19. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/_constants.py +0 -0
  20. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/_pagination.py +0 -0
  21. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/client.py +0 -0
  22. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/errors.py +0 -0
  23. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/__init__.py +0 -0
  24. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/_base.py +0 -0
  25. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/analytics.py +0 -0
  26. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/api_keys.py +0 -0
  27. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/applications.py +0 -0
  28. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/common.py +0 -0
  29. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/cron_jobs.py +0 -0
  30. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/deliveries.py +0 -0
  31. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/dlq.py +0 -0
  32. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/endpoints.py +0 -0
  33. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/event_types.py +0 -0
  34. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/events.py +0 -0
  35. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/filters.py +0 -0
  36. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/messages.py +0 -0
  37. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/organizations.py +0 -0
  38. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/portal_tokens.py +0 -0
  39. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/routes.py +0 -0
  40. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/schemas.py +0 -0
  41. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/subscriptions.py +0 -0
  42. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/transforms.py +0 -0
  43. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/models/tunnels.py +0 -0
  44. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/py.typed +0 -0
  45. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/__init__.py +0 -0
  46. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/_base.py +0 -0
  47. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/analytics.py +0 -0
  48. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/api_keys.py +0 -0
  49. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/applications.py +0 -0
  50. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/cron_jobs.py +0 -0
  51. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/deliveries.py +0 -0
  52. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/destinations.py +0 -0
  53. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/dlq.py +0 -0
  54. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/endpoints.py +0 -0
  55. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/event_types.py +0 -0
  56. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/events.py +0 -0
  57. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/filters.py +0 -0
  58. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/message_log.py +0 -0
  59. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/messages.py +0 -0
  60. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/organizations.py +0 -0
  61. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/portal_tokens.py +0 -0
  62. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/routes.py +0 -0
  63. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/schemas.py +0 -0
  64. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/sources.py +0 -0
  65. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/subscriptions.py +0 -0
  66. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/transforms.py +0 -0
  67. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/resources/tunnels.py +0 -0
  68. {hookbase-2.7.0 → hookbase-2.9.0}/src/hookbase/webhook.py +0 -0
  69. {hookbase-2.7.0 → hookbase-2.9.0}/tests/__init__.py +0 -0
  70. {hookbase-2.7.0 → hookbase-2.9.0}/tests/conftest.py +0 -0
  71. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/__init__.py +0 -0
  72. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_applications.py +0 -0
  73. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_cron_jobs.py +0 -0
  74. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_dlq.py +0 -0
  75. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_messages.py +0 -0
  76. {hookbase-2.7.0 → hookbase-2.9.0}/tests/resources/test_sources.py +0 -0
  77. {hookbase-2.7.0 → hookbase-2.9.0}/tests/test_client.py +0 -0
  78. {hookbase-2.7.0 → hookbase-2.9.0}/tests/test_errors.py +0 -0
  79. {hookbase-2.7.0 → hookbase-2.9.0}/tests/test_pagination.py +0 -0
  80. {hookbase-2.7.0 → hookbase-2.9.0}/tests/test_webhook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hookbase
3
- Version: 2.7.0
3
+ Version: 2.9.0
4
4
  Summary: Official Python SDK for the Hookbase webhook management platform
5
5
  Project-URL: Homepage, https://hookbase.app
6
6
  Project-URL: Documentation, https://www.hookbase.app/docs/send/sdk
@@ -0,0 +1 @@
1
+ __version__ = "2.9.0"
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import json
4
4
  from typing import Any, Literal
5
5
 
6
- from pydantic import field_validator, model_validator
6
+ from pydantic import Field, field_validator, model_validator
7
7
 
8
8
  from ._base import HookbaseModel
9
9
 
@@ -209,7 +209,10 @@ class UpdateDestinationParams(HookbaseModel):
209
209
 
210
210
  class TestResult(HookbaseModel):
211
211
  success: bool
212
- status_code: int | None = None
213
- duration: float | None = None
212
+ # The API answers with `status`/`latencyMs` (api/src/routes/destinations.ts), not the
213
+ # `statusCode`/`duration` that HookbaseModel's to_camel alias_generator would otherwise
214
+ # expect for these field names — override the alias explicitly rather than rely on it.
215
+ status_code: int | None = Field(default=None, alias="status")
216
+ duration: float | None = Field(default=None, alias="latencyMs")
214
217
  response_body: str | None = None
215
218
  error: str | None = None
@@ -7,12 +7,28 @@ from pydantic import field_validator
7
7
 
8
8
  from ._base import HookbaseModel
9
9
 
10
+ # Providers the API will accept for a source.
11
+ #
12
+ # Mirrors SUPPORTED_SIGNATURE_PROVIDERS in the API (api/src/utils/signature-schemes.ts), which
13
+ # is derived from the signature scheme table rather than restated. Regenerate with
14
+ # `npx tsx scripts/print-source-enums.ts` in the api package; do not hand-extend this Literal,
15
+ # because a value the API does not accept is a 400 the type promised would not happen.
16
+ #
17
+ # Removed in the 2026-09 correction: "sendgrid", "mailgun" and "linear". All three were
18
+ # advertised here from the beginning and none was ever accepted by the API. SendGrid signs with
19
+ # ECDSA and Mailgun puts the signature in the POST body, so neither fits this scheme model;
20
+ # Linear's scheme is real but unverified against its docs. Use "custom" for all three.
21
+ #
22
+ # "svix" is an alias of "standard-webhooks"; both resolve to the same scheme server-side.
10
23
  SourceProvider = Literal[
11
- "generic", "github", "stripe", "shopify", "slack", "twilio",
12
- "sendgrid", "mailgun", "paddle", "linear", "svix", "custom",
24
+ "bitbucket", "custom", "generic", "github", "gitlab", "heroku",
25
+ "lemonsqueezy", "paddle", "sentry", "shopify", "slack", "standard-webhooks",
26
+ "stripe", "svix", "twilio", "typeform", "zoom",
13
27
  ]
14
- DedupStrategy = Literal["none", "header", "payload_hash", "event_id"]
15
- IpFilterMode = Literal["none", "allowlist", "denylist"]
28
+ # Corrected alongside SourceProvider: "header" and "event_id" were never accepted, and the three
29
+ # values the API actually defaults to and documents were missing. "auto" is the default.
30
+ DedupStrategy = Literal["auto", "provider_id", "payload_hash", "idempotency_key", "none"]
31
+ IpFilterMode = Literal["none", "allowlist", "denylist", "both"]
16
32
  # HTTP verbs an ingest endpoint can be restricted to. OPTIONS is excluded: CORS preflight is
17
33
  # answered before ingest runs, so it is never gateable.
18
34
  IngestMethod = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"]
@@ -272,10 +272,24 @@ def test_update_destination_params_throttle_serializes_camelcase():
272
272
 
273
273
 
274
274
  def test_test_destination(mock_api, client):
275
+ # The API answers with `status`/`latencyMs` (api/src/routes/destinations.ts), not
276
+ # `statusCode`/`duration` — the model aliases onto those field names explicitly.
275
277
  mock_api.post("/api/destinations/dst_1/test").respond(200, json={
276
- "success": True, "statusCode": 200, "duration": 150.5,
278
+ "success": True, "status": 200, "latencyMs": 150.5, "responseBody": "OK",
277
279
  })
278
280
  result = client.destinations.test("dst_1")
279
281
  assert isinstance(result, TestResult)
280
282
  assert result.success is True
281
283
  assert result.status_code == 200
284
+ assert result.duration == 150.5
285
+ assert result.response_body == "OK"
286
+
287
+
288
+ def test_test_destination_failure_surfaces_error(mock_api, client):
289
+ mock_api.post("/api/destinations/dst_1/test").respond(200, json={
290
+ "success": False, "error": "Network error",
291
+ })
292
+ result = client.destinations.test("dst_1")
293
+ assert result.success is False
294
+ assert result.error == "Network error"
295
+ assert result.status_code is None
@@ -1 +0,0 @@
1
- __version__ = "2.7.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes