diff --git a/.fern/metadata.json b/.fern/metadata.json
index e0564f1..04f5b38 100644
--- a/.fern/metadata.json
+++ b/.fern/metadata.json
@@ -1,7 +1,7 @@
{
- "cliVersion": "5.28.2",
+ "cliVersion": "5.38.0",
"generatorName": "fernapi/fern-python-sdk",
- "generatorVersion": "5.12.12",
+ "generatorVersion": "5.12.11",
"generatorConfig": {
"package_name": "newscatcher_catchall",
"client": {
@@ -9,10 +9,10 @@
"filename": "client.py"
}
},
- "originGitCommit": "22c183ea79ae5db44081d7400064d8907991d81b",
+ "originGitCommit": "de5cbc2ed91fe4cad1702c385a0b0b6b986006f6",
"originGitCommitIsDirty": true,
"invokedBy": "ci",
"requestedVersion": "AUTO",
"ciProvider": "unknown",
- "sdkVersion": "2.0.0"
+ "sdkVersion": "3.0.0"
}
\ No newline at end of file
diff --git a/README.md b/README.md
index 230a714..acc571a 100644
--- a/README.md
+++ b/README.md
@@ -216,3 +216,4 @@ On the other hand, contributions to the README are always very welcome!
+
diff --git a/changelog.md b/changelog.md
index d67787f..1273fa0 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,14 @@
+## 3.0.0 - 2026-05-27
+### Breaking Changes
+* **`MonitorsClient.create_monitor()` and `MonitorsClient.update_monitor()`** — the `webhook` parameter (type `WebhookDto`) has been replaced by `webhook_ids` (type `list[str]`); rename the argument and pass a list of webhook ID strings instead of a `WebhookDto` object.
+* **`JobsClient.submit()` and `JobsClient.initialize()`** — same `webhook` → `webhook_ids` rename applies; update all callers to pass a list of webhook ID strings.
+### Added
+* **`client.webhooks` (`WebhooksClient` / `AsyncWebhooksClient`)** — new client for full webhook lifecycle management: `list_webhooks()`, `create_webhook()`, `get_webhook()`, `update_webhook()`, `delete_webhook()`, `test_webhook()`, `assign_webhook_resource()`, `remove_webhook_resource()`, `list_webhook_resources()`, `list_webhooks_for_resource()`, and `get_webhook_delivery_history()` (sync and async).
+* **`client.projects` (`ProjectsClient` / `AsyncProjectsClient`)** — new client for project lifecycle management: `list_projects()`, `create_project()`, `get_project()`, `update_project()`, `delete_project()`, `get_project_overview()`, `list_project_resources()`, `add_resource_to_project()`, and `remove_resource_from_project()` (sync and async).
+* **`JobsClient.validate_query()`** — new method (sync and async) that checks whether a query is well-formed before job submission, returning a `ValidateQueryResponseDto` with a status level, issues, and suggestions.
+* **`project_id` and `webhook_ids` optional parameters** — added to `get_user_jobs()`, `list_monitors()`, `list_datasets()`, `submit()`, `initialize()`, and `create_monitor()` to filter or assign resources to a project and attach webhook notifications.
+* See full changelog for all changes
+
## 2.0.0 - 2026-05-19
### Breaking Changes
* **`DatasetsClient.list_entities_in_dataset()`** — now issues a POST to `.../entities/list` instead of a GET to `.../entities`; filter parameters are sent as a JSON body instead of query parameters, and optional filter params now default to `OMIT` (omitted entirely) instead of `None`; remove any `None` arguments and update any code that inspects raw HTTP requests.
diff --git a/poetry.lock b/poetry.lock
index b722478..4d94723 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -2,15 +2,15 @@
[[package]]
name = "aiohappyeyeballs"
-version = "2.6.1"
+version = "2.6.2"
description = "Happy Eyeballs for asyncio"
optional = true
-python-versions = ">=3.9"
+python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"aiohttp\""
files = [
- {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"},
- {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"},
+ {file = "aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4"},
+ {file = "aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64"},
]
[[package]]
@@ -247,14 +247,14 @@ files = [
[[package]]
name = "certifi"
-version = "2026.4.22"
+version = "2026.5.20"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
- {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"},
- {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"},
+ {file = "certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897"},
+ {file = "certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d"},
]
[[package]]
@@ -523,14 +523,14 @@ httpx = ">=0.27.0"
[[package]]
name = "idna"
-version = "3.15"
+version = "3.16"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"},
- {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"},
+ {file = "idna-3.16-py3-none-any.whl", hash = "sha256:cc246e3a3f89580c3a951b5ad298ca4638078b2cdd4f115654332b5c26daded5"},
+ {file = "idna-3.16.tar.gz", hash = "sha256:d7a6da03db833450fca25d2358ac9ff06cd624577a4aea3a596d5c0f77b8e03d"},
]
[package.extras]
@@ -1130,23 +1130,23 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests
[[package]]
name = "pytest-asyncio"
-version = "1.3.0"
+version = "1.4.0"
description = "Pytest support for asyncio"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5"},
- {file = "pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5"},
+ {file = "pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1"},
+ {file = "pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42"},
]
[package.dependencies]
backports-asyncio-runner = {version = ">=1.1,<2", markers = "python_version < \"3.11\""}
-pytest = ">=8.2,<10"
+pytest = ">=8.4,<10"
typing-extensions = {version = ">=4.12", markers = "python_version < \"3.13\""}
[package.extras]
-docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"]
+docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)", "sphinx-tabs (>=3.5)"]
testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"]
[[package]]
@@ -1342,141 +1342,117 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
[[package]]
name = "yarl"
-version = "1.23.0"
+version = "1.24.2"
description = "Yet another URL library"
optional = true
python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"aiohttp\""
files = [
- {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107"},
- {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d"},
- {file = "yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4"},
- {file = "yarl-1.23.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750"},
- {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6"},
- {file = "yarl-1.23.0-cp310-cp310-win32.whl", hash = "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d"},
- {file = "yarl-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb"},
- {file = "yarl-1.23.0-cp310-cp310-win_arm64.whl", hash = "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220"},
- {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99"},
- {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c"},
- {file = "yarl-1.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598"},
- {file = "yarl-1.23.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc"},
- {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2"},
- {file = "yarl-1.23.0-cp311-cp311-win32.whl", hash = "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5"},
- {file = "yarl-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46"},
- {file = "yarl-1.23.0-cp311-cp311-win_arm64.whl", hash = "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928"},
- {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860"},
- {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069"},
- {file = "yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51"},
- {file = "yarl-1.23.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86"},
- {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34"},
- {file = "yarl-1.23.0-cp312-cp312-win32.whl", hash = "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d"},
- {file = "yarl-1.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e"},
- {file = "yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9"},
- {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e"},
- {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5"},
- {file = "yarl-1.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4"},
- {file = "yarl-1.23.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a"},
- {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543"},
- {file = "yarl-1.23.0-cp313-cp313-win32.whl", hash = "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957"},
- {file = "yarl-1.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3"},
- {file = "yarl-1.23.0-cp313-cp313-win_arm64.whl", hash = "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3"},
- {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa"},
- {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120"},
- {file = "yarl-1.23.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9"},
- {file = "yarl-1.23.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6"},
- {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5"},
- {file = "yarl-1.23.0-cp313-cp313t-win32.whl", hash = "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595"},
- {file = "yarl-1.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090"},
- {file = "yarl-1.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144"},
- {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912"},
- {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474"},
- {file = "yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52"},
- {file = "yarl-1.23.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6"},
- {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe"},
- {file = "yarl-1.23.0-cp314-cp314-win32.whl", hash = "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169"},
- {file = "yarl-1.23.0-cp314-cp314-win_amd64.whl", hash = "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70"},
- {file = "yarl-1.23.0-cp314-cp314-win_arm64.whl", hash = "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e"},
- {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679"},
- {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412"},
- {file = "yarl-1.23.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6"},
- {file = "yarl-1.23.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2"},
- {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4"},
- {file = "yarl-1.23.0-cp314-cp314t-win32.whl", hash = "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4"},
- {file = "yarl-1.23.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2"},
- {file = "yarl-1.23.0-cp314-cp314t-win_arm64.whl", hash = "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25"},
- {file = "yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f"},
- {file = "yarl-1.23.0.tar.gz", hash = "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5"},
+ {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12"},
+ {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0"},
+ {file = "yarl-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15c0b5e49d3c44e2a0b93e6a49476c5edad0a7686b92c395765a7ea775572a75"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:246d32a53a947c8f0189f5d699cbd4c7036de45d9359e13ba238d1239678c727"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:64480fb3e4d4ed9ed71c48a91a477384fc342a50ca30071d2f8a88d51d9c9413"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:349de4701dc3760b6e876628423a8f147ef4f5599d10aba1e10702075d424ed9"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d162677af8d5d3d6ebab8394b021f4d041ac107a4b705873148a77a49dc9e1b2"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5f5c6ec23a9043f2d139cc072f53dd23168d202a334b9b2fda8de4c3e890d90"},
+ {file = "yarl-1.24.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:60de6742447fbbf697f16f070b8a443f1b5fe6ca3826fbef9fe70ecd5328e643"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acf93187c3710e422368eb768aee98db551ec7c85adc250207a95c16548ab7ac"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f4b0352fd41fd34b6651934606268816afd6914d09626f9bcbbf018edb0afb3f"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6b208bb939099b4b297438da4e9b25357f0b1c791888669b963e45b203ea9f36"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4b85b8825e631295ff4bc8943f7471d54c533a9360bbe15ebb38e018b555bb8a"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e26acf20c26cb4fefc631fdb75aca2a6b8fa8b7b5d7f204fb6a8f1e63c706f53"},
+ {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:819ca24f8eafcfb683c1bd5f44f2f488cea1274eb8944731ffd2e1f10f619342"},
+ {file = "yarl-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:5cb0f995a901c36be096ccbf4c673591c2faabbe96279598ffaec8c030f85bf4"},
+ {file = "yarl-1.24.2-cp310-cp310-win_arm64.whl", hash = "sha256:f408eace7e22a68b467a0562e0d27d322f91fe3eaaa6f466b962c6cfaea9fa39"},
+ {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1"},
+ {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c"},
+ {file = "yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003"},
+ {file = "yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b"},
+ {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5"},
+ {file = "yarl-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:f8fdbcff8b2c7c9284e60c196f693588598ddcee31e11c18e14949ce44519d45"},
+ {file = "yarl-1.24.2-cp311-cp311-win_arm64.whl", hash = "sha256:b32c37a7a337e90822c45797bf3d79d60875cfcccd3ecc80e9f453d87026c122"},
+ {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8"},
+ {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2"},
+ {file = "yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c"},
+ {file = "yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c"},
+ {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1"},
+ {file = "yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad"},
+ {file = "yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30"},
+ {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536"},
+ {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607"},
+ {file = "yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617"},
+ {file = "yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056"},
+ {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992"},
+ {file = "yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656"},
+ {file = "yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461"},
+ {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2"},
+ {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630"},
+ {file = "yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208"},
+ {file = "yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b"},
+ {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8"},
+ {file = "yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0"},
+ {file = "yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57"},
+ {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b"},
+ {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761"},
+ {file = "yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf"},
+ {file = "yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe"},
+ {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd"},
+ {file = "yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215"},
+ {file = "yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d"},
+ {file = "yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9"},
+ {file = "yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8"},
]
[package.dependencies]
diff --git a/pyproject.toml b/pyproject.toml
index 670d94f..7bf8f2c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ dynamic = ["version"]
[tool.poetry]
name = "newscatcher-catchall-sdk"
-version = "2.0.0"
+version = "3.0.0"
description = ""
readme = "README.md"
authors = []
diff --git a/reference.md b/reference.md
index 2857ea3..127c459 100644
--- a/reference.md
+++ b/reference.md
@@ -35,7 +35,9 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.jobs.get_user_jobs()
+client.jobs.get_user_jobs(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+)
```
@@ -83,6 +85,89 @@ client.jobs.get_user_jobs()
-
+**project_id:** `typing.Optional[str]` — Filter results to resources belonging to this project.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.jobs.validate_query(...) -> ValidateQueryResponseDto
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Checks whether a query is well-formed and likely to produce good results before submitting a job.
+
+Returns a quality assessment with a status level, identified issues, and actionable suggestions.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.jobs.validate_query(
+ query="Series B funding rounds for SaaS startups",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**query:** `str` — Plain text query to validate.
+
+
+
+
+
+-
+
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -337,6 +422,22 @@ Only valid when `connected_dataset_ids` is set; otherwise ignored. Records where
-
+**project_id:** `typing.Optional[str]` — Project to assign this job to. The job appears in the project's resource list immediately after submission.
+
+
+
+
+
+-
+
+**webhook_ids:** `typing.Optional[typing.List[str]]` — IDs of webhooks to notify when the job completes. Maximum 5 per job.
+
+
+
+
+
+-
+
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -706,7 +807,9 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.monitors.list_monitors()
+client.monitors.list_monitors(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+)
```
@@ -754,6 +857,14 @@ client.monitors.list_monitors()
-
+**project_id:** `typing.Optional[str]` — Filter results to resources belonging to this project.
+
+
+
+
+
+-
+
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -793,7 +904,7 @@ Create a scheduled monitor based on a reference job.
-
```python
-from newscatcher_catchall import CatchAllApi, WebhookDto
+from newscatcher_catchall import CatchAllApi
from newscatcher_catchall.environment import CatchAllApiEnvironment
client = CatchAllApi(
@@ -805,13 +916,9 @@ client.monitors.create_monitor(
reference_job_id="5f0c9087-85cb-4917-b3c7-e5a5eff73a0c",
schedule="every day at 12 PM",
timezone="UTC",
- webhook=WebhookDto(
- url="https://your-endpoint.com/webhook",
- method="POST",
- headers={
- "Authorization": "Bearer your_token_here"
- },
- ),
+ webhook_ids=[
+ "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
+ ],
limit=10,
backfill=True,
)
@@ -862,7 +969,12 @@ If the schedule includes a timezone abbreviation (for example, `"every day at 9a
-
-**webhook:** `typing.Optional[WebhookDto]` — Optional webhook to receive notifications when jobs complete.
+**webhook_ids:** `typing.Optional[typing.List[str]]`
+
+IDs of centralized webhooks to notify on each run completion.
+Passing IDs here is equivalent to calling
+`POST /catchAll/webhooks/{webhook_id}/resources` for each ID after creation.
+Maximum 5 per monitor.
@@ -890,6 +1002,14 @@ If false, no gap filling occurs and the first run uses the current cron window o
-
+**project_id:** `typing.Optional[str]` — Project to assign this monitor to. The monitor appears in the project's resource list after creation.
+
+
+
+
+
+-
+
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -1395,7 +1515,7 @@ Update the webhook configuration for an existing monitor.
-
```python
-from newscatcher_catchall import CatchAllApi, WebhookDto
+from newscatcher_catchall import CatchAllApi
from newscatcher_catchall.environment import CatchAllApiEnvironment
client = CatchAllApi(
@@ -1405,13 +1525,9 @@ client = CatchAllApi(
client.monitors.update_monitor(
monitor_id="monitor_id",
- webhook=WebhookDto(
- url="https://new-endpoint.com/webhook",
- method="POST",
- headers={
- "Authorization": "Bearer new_token_xyz"
- },
- ),
+ webhook_ids=[
+ "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
+ ],
)
```
@@ -1436,7 +1552,11 @@ client.monitors.update_monitor(
-
-**webhook:** `typing.Optional[WebhookDto]` — Updated webhook configuration.
+**webhook_ids:** `typing.Optional[typing.List[str]]`
+
+Updated list of centralized webhook IDs for this monitor.
+
+Replaces all existing webhook assignments. Pass an empty array `[]` to clear all assignments. Omit to leave existing assignments unchanged.
@@ -1464,8 +1584,8 @@ client.monitors.update_monitor(
-## Entities
-client.entities.list_entities(...) -> EntityListResponse
+## Webhooks
+client.webhooks.list_webhooks(...) -> ListWebhooksResponseDto
-
@@ -1477,7 +1597,7 @@ client.monitors.update_monitor(
-
-Returns a paginated list of entities belonging to the authenticated organization. Supports filtering by status and entity type, and sorting by name, status, or creation date.
+Returns a paginated list of webhooks belonging to the organization.
@@ -1500,9 +1620,7 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.entities.list_entities(
- search="NewsCatcher",
-)
+client.webhooks.list_webhooks()
```
@@ -1526,7 +1644,7 @@ client.entities.list_entities(
-
-**page_size:** `typing.Optional[int]` — Number of entities per page.
+**page_size:** `typing.Optional[int]` — Number of webhooks per page.
@@ -1534,7 +1652,7 @@ client.entities.list_entities(
-
-**search:** `typing.Optional[str]` — Filter entities by name (case-insensitive substring match).
+**search:** `typing.Optional[str]` — Filter results by text (case-insensitive substring match).
@@ -1542,124 +1660,154 @@ client.entities.list_entities(
-
-**status:** `typing.Optional[EntityStatus]`
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
--
-**entity_type:** `typing.Optional[EntityType]`
-
+
+client.webhooks.create_webhook(...) -> CreateWebhookResponseDto
-
-**sort_by:** `typing.Optional[EntitySortBy]`
-
-
-
+#### 📝 Description
-
-**sort_order:** `typing.Optional[SortOrder]`
-
-
-
-
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
+Creates a new webhook endpoint for the organization.
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+client.webhooks.create_webhook(
+ name="Layoffs Alert",
+ url="https://hooks.slack.com/services/T000/B000/xxx",
+ type="slack",
+ delivery_mode="full",
+)
+
+```
+
+
-
-client.entities.create_entity(...) -> CreateEntityResponse
+#### ⚙️ Parameters
+
-
-#### 📝 Description
-
-
+**name:** `str` — Human-readable label for this webhook.
+
+
+
+
-
-Creates a new company entity and begins background enrichment.
+**url:** `str`
-The entity status starts as `pending` and transitions to `ready` once
-enrichment completes. Provide as much identifying information as
-possible — `domain` is the highest-signal field because it is
-unambiguous.
+Destination URL that receives the payload. Must use HTTPS. IP addresses are not accepted.
+
+Type-specific URL requirements:
+- `slack`: Must start with `https://hooks.slack.com/`.
+- `teams`: Hostname must match `*.webhook.office.com` or `*.webhook.office365.com`.
+- `generic`: Any valid HTTPS domain.
+- `custom`: Any valid HTTPS domain.
+
+When `type` is omitted, it is auto-detected from the URL.
+
+
+
+-
+
+**type:** `typing.Optional[WebhookType]`
+
-#### 🔌 Usage
-
-
+**delivery_mode:** `typing.Optional[DeliveryMode]`
+
+
+
+
-
-```python
-from newscatcher_catchall import CatchAllApi, AdditionalAttributes, CompanyAttributes
-from newscatcher_catchall.environment import CatchAllApiEnvironment
-
-client = CatchAllApi(
- api_key="",
- environment=CatchAllApiEnvironment.DEFAULT,
-)
+**method:** `typing.Optional[HttpMethod]`
+
+
+
-client.entities.create_entity(
- name="NewsCatcher",
- entity_type="company",
- description="AI-powered news data provider",
- additional_attributes=AdditionalAttributes(
- company_attributes=CompanyAttributes(
- domain="newscatcherapi.com",
- key_persons=[
- "Artem Bugara",
- "Maksym Sugonyaka"
- ],
- alternative_names=[
- "NC",
- "NewsCatcher API"
- ],
- ),
- ),
-)
+
+-
-```
+**headers:** `typing.Optional[typing.Dict[str, str]]` — Custom HTTP headers forwarded with each delivery.
+
+
+
+-
+
+**params:** `typing.Optional[typing.Dict[str, str]]` — Query parameters appended to the webhook URL.
+
-#### ⚙️ Parameters
-
-
+**auth:** `typing.Optional[CreateWebhookRequestDtoAuth]`
+
+Authentication forwarded with each delivery. Supported types:
+- `bearer`: Adds an `Authorization: Bearer ` header.
+- `api_key`: Adds a custom header with the specified name and value.
+- `basic`: Adds an `Authorization: Basic ` header.
+
+
+
+
-
-**request:** `CreateEntityRequest`
+**formatter_config:** `typing.Optional[typing.Dict[str, typing.Any]]` — Custom payload transformation configuration. Required only when `type` is `custom`.
@@ -1679,7 +1827,7 @@ client.entities.create_entity(
-client.entities.create_entities_batch(...) -> CreateEntitiesBatchResponse
+client.webhooks.get_webhook(...) -> GetWebhookResponseDto
-
@@ -1691,9 +1839,7 @@ client.entities.create_entity(
-
-Creates multiple entities in a single request. Each entity is processed independently — a failure in one does not affect others.
-
-Returns an array of `{id, status}` objects in the same order as the input array.
+Returns the full configuration of a single webhook by ID.
@@ -1708,7 +1854,7 @@ Returns an array of `{id, status}` objects in the same order as the input array.
-
```python
-from newscatcher_catchall import CatchAllApi, CreateEntityRequest, AdditionalAttributes, CompanyAttributes
+from newscatcher_catchall import CatchAllApi
from newscatcher_catchall.environment import CatchAllApiEnvironment
client = CatchAllApi(
@@ -1716,39 +1862,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.entities.create_entities_batch(
- entities=[
- CreateEntityRequest(
- name="OpenAI",
- entity_type="company",
- description="Artificial intelligence research company",
- additional_attributes=AdditionalAttributes(
- company_attributes=CompanyAttributes(
- domain="openai.com",
- key_persons=[
- "Sam Altman"
- ],
- alternative_names=[
- "Open AI"
- ],
- ),
- ),
- ),
- CreateEntityRequest(
- name="Stripe",
- entity_type="company",
- description="Online payment processing platform",
- additional_attributes=AdditionalAttributes(
- company_attributes=CompanyAttributes(
- domain="stripe.com",
- key_persons=[
- "Patrick Collison",
- "John Collison"
- ],
- ),
- ),
- )
- ],
+client.webhooks.get_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
)
```
@@ -1765,10 +1880,82 @@ client.entities.create_entities_batch(
-
-**entities:** `typing.List[CreateEntityRequest]`
+**webhook_id:** `str` — Unique webhook identifier.
+
+
+
-Array of entities to create. Each item follows the same schema
-as single entity creation.
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.webhooks.delete_webhook(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Permanently deletes a webhook and removes all resource assignments.
+
+Assigned jobs and monitors no longer trigger delivery to this webhook. This operation cannot be undone.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.webhooks.delete_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**webhook_id:** `str` — Unique webhook identifier.
@@ -1788,7 +1975,7 @@ as single entity creation.
-client.entities.get_entity(...) -> EntityResponse
+client.webhooks.update_webhook(...) -> UpdateWebhookResponseDto
-
@@ -1800,7 +1987,7 @@ as single entity creation.
-
-Returns a single entity by ID with all attributes and current status.
+Updates one or more fields of an existing webhook.
@@ -1823,8 +2010,10 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.entities.get_entity(
- entity_id="854198fa-f702-49db-a381-0427fa87f173",
+client.webhooks.update_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ name="Layoffs Alert (EU)",
+ is_active=False,
)
```
@@ -1841,7 +2030,87 @@ client.entities.get_entity(
-
-**entity_id:** `str` — Unique entity identifier.
+**webhook_id:** `str` — Unique webhook identifier.
+
+
+
+
+
+-
+
+**name:** `typing.Optional[str]` — Updated webhook name.
+
+
+
+
+
+-
+
+**url:** `typing.Optional[str]` — Updated destination URL. Must use HTTPS. Type-specific URL rules apply.
+
+
+
+
+
+-
+
+**type:** `typing.Optional[WebhookType]`
+
+
+
+
+
+-
+
+**delivery_mode:** `typing.Optional[DeliveryMode]`
+
+
+
+
+
+-
+
+**method:** `typing.Optional[HttpMethod]`
+
+
+
+
+
+-
+
+**headers:** `typing.Optional[typing.Dict[str, str]]` — Updated HTTP headers. Replaces existing headers entirely.
+
+
+
+
+
+-
+
+**params:** `typing.Optional[typing.Dict[str, str]]` — Updated query parameters. Replaces existing params entirely.
+
+
+
+
+
+-
+
+**auth:** `typing.Optional[UpdateWebhookRequestDtoAuth]` — Updated authentication configuration. Replaces existing auth entirely.
+
+
+
+
+
+-
+
+**formatter_config:** `typing.Optional[typing.Dict[str, typing.Any]]` — Updated formatter configuration.
+
+
+
+
+
+-
+
+**is_active:** `typing.Optional[bool]` — Set to `false` to disable delivery without deleting the webhook.
@@ -1861,7 +2130,7 @@ client.entities.get_entity(
-client.entities.delete_entity(...)
+client.webhooks.test_webhook(...) -> TestWebhookResponseDto
-
@@ -1873,8 +2142,9 @@ client.entities.get_entity(
-
-Permanently deletes an entity. The entity is removed from all
-datasets and the search index. This operation cannot be undone.
+Sends a test HTTP request to the webhook URL using the webhook's configured method, headers, and auth. Returns the response from the target endpoint.
+
+Use this to verify URL reachability and authentication before attaching the webhook to a live job or monitor.
@@ -1897,8 +2167,12 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.entities.delete_entity(
- entity_id="854198fa-f702-49db-a381-0427fa87f173",
+client.webhooks.test_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ payload={
+ "test": True,
+ "message": "CatchAll webhook test"
+ },
)
```
@@ -1915,7 +2189,18 @@ client.entities.delete_entity(
-
-**entity_id:** `str` — Unique entity identifier.
+**webhook_id:** `str` — Unique webhook identifier.
+
+
+
+
+
+-
+
+**payload:** `typing.Optional[typing.Dict[str, typing.Any]]`
+
+Custom payload to send in the test request. If omitted, a synthetic
+test payload is sent.
@@ -1935,7 +2220,7 @@ client.entities.delete_entity(
-client.entities.update_entity(...) -> EntityResponse
+client.webhooks.list_webhook_resources(...) -> ListWebhookResourcesResponseDto
-
@@ -1947,7 +2232,7 @@ client.entities.delete_entity(
-
-Updates one or more fields of an existing entity.
+Returns a paginated list of resources currently assigned to this webhook.
@@ -1962,7 +2247,7 @@ Updates one or more fields of an existing entity.
-
```python
-from newscatcher_catchall import CatchAllApi, AdditionalAttributes, CompanyAttributes
+from newscatcher_catchall import CatchAllApi
from newscatcher_catchall.environment import CatchAllApiEnvironment
client = CatchAllApi(
@@ -1970,18 +2255,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.entities.update_entity(
- entity_id="854198fa-f702-49db-a381-0427fa87f173",
- description="Updated description",
- additional_attributes=AdditionalAttributes(
- company_attributes=CompanyAttributes(
- alternative_names=[
- "NC",
- "NewsCatcher API",
- "NCA"
- ],
- ),
- ),
+client.webhooks.list_webhook_resources(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
)
```
@@ -1998,7 +2273,7 @@ client.entities.update_entity(
-
-**entity_id:** `str` — Unique entity identifier.
+**webhook_id:** `str` — Unique webhook identifier.
@@ -2006,7 +2281,7 @@ client.entities.update_entity(
-
-**name:** `typing.Optional[str]` — Updated entity name.
+**resource_type:** `typing.Optional[MappableResourceType]`
@@ -2014,7 +2289,7 @@ client.entities.update_entity(
-
-**description:** `typing.Optional[str]` — Updated description.
+**page:** `typing.Optional[int]` — Page number to retrieve.
@@ -2022,7 +2297,7 @@ client.entities.update_entity(
-
-**additional_attributes:** `typing.Optional[AdditionalAttributes]`
+**page_size:** `typing.Optional[int]` — Number of assignments per page.
@@ -2042,8 +2317,7 @@ client.entities.update_entity(
-## Datasets
-client.datasets.list_datasets(...) -> DatasetListResponse
+client.webhooks.assign_webhook_resource(...) -> AssignWebhookResourceResponseDto
-
@@ -2055,7 +2329,11 @@ client.entities.update_entity(
-
-Returns a paginated list of datasets belonging to the authenticated organization. Supports filtering by status and sorting by name, status, or creation date.
+Attaches a job, monitor, or monitor group to the webhook. When the
+resource completes, the webhook receives a delivery.
+
+A single webhook can be assigned to multiple resources. Each resource
+can have up to 5 webhooks assigned.
@@ -2078,8 +2356,10 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.list_datasets(
- search="Portfolio",
+client.webhooks.assign_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="monitor",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
)
```
@@ -2096,55 +2376,1849 @@ client.datasets.list_datasets(
-
-**page:** `typing.Optional[int]` — Page number to retrieve.
+**webhook_id:** `str` — Unique webhook identifier.
+
+
+
+
+
+-
+
+**resource_type:** `MappableResourceType` — Type of resource to assign.
+
+
+
+
+
+-
+
+**resource_id:** `str` — ID of the resource to assign.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+client.webhooks.remove_webhook_resource(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Detaches a resource from this webhook. Completions of the resource no longer trigger delivery to this webhook.
+
+The webhook and the resource itself are not deleted.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.webhooks.remove_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**webhook_id:** `str` — Unique webhook identifier.
+
+
+
+
+
+-
+
+**resource_type:** `MappableResourceType`
+
+
+
+
+
+-
+
+**resource_id:** `str` — Unique resource identifier.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.webhooks.list_webhooks_for_resource(...) -> ListWebhooksResponseDto
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns all webhooks currently assigned to the given resource.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.webhooks.list_webhooks_for_resource(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**resource_type:** `MappableResourceType`
+
+
+
+
+
+-
+
+**resource_id:** `str` — Unique resource identifier.
+
+
+
+
+
+-
+
+**is_active:** `typing.Optional[bool]` — Filter by active status. Omit to return webhooks regardless of status.
+
+
+
+
+
+-
+
+**page:** `typing.Optional[int]` — Page number to retrieve.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of webhooks per page.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.webhooks.get_webhook_delivery_history(...) -> DeliveryHistoryResponseDto
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a paginated delivery log for a given resource, ordered by timestamp descending.
+
+Each record shows the webhook dispatched, the HTTP status code returned, delivery outcome, and any error or warning messages. Use this to debug failed deliveries or audit dispatch activity.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.webhooks.get_webhook_delivery_history(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**resource_type:** `MappableResourceType` — Type of the resource to retrieve delivery history for.
+
+
+
+
+
+-
+
+**resource_id:** `str` — Identifier of the resource to retrieve delivery history for.
+
+
+
+
+
+-
+
+**page:** `typing.Optional[int]` — Page number to retrieve.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of records per page.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Entities
+client.entities.list_entities(...) -> EntityListResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a paginated list of entities belonging to the authenticated organization. Supports filtering by status and entity type, and sorting by name, status, or creation date.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.list_entities(
+ search="NewsCatcher",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**page:** `typing.Optional[int]` — Page number to retrieve.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of entities per page.
+
+
+
+
+
+-
+
+**search:** `typing.Optional[str]` — Filter entities by name (case-insensitive substring match).
+
+
+
+
+
+-
+
+**status:** `typing.Optional[EntityStatus]`
+
+
+
+
+
+-
+
+**entity_type:** `typing.Optional[EntityType]`
+
+
+
+
+
+-
+
+**sort_by:** `typing.Optional[EntitySortBy]`
+
+
+
+
+
+-
+
+**sort_order:** `typing.Optional[SortOrder]`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.entities.create_entity(...) -> CreateEntityResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates a new company entity and begins background enrichment.
+
+The entity status starts as `pending` and transitions to `ready` once
+enrichment completes. Provide as much identifying information as
+possible — `domain` is the highest-signal field because it is
+unambiguous.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi, AdditionalAttributes, CompanyAttributes
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.create_entity(
+ name="NewsCatcher",
+ entity_type="company",
+ description="AI-powered news data provider",
+ additional_attributes=AdditionalAttributes(
+ company_attributes=CompanyAttributes(
+ domain="newscatcherapi.com",
+ key_persons=[
+ "Artem Bugara",
+ "Maksym Sugonyaka"
+ ],
+ alternative_names=[
+ "NC",
+ "NewsCatcher API"
+ ],
+ ),
+ ),
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `CreateEntityRequest`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.entities.create_entities_batch(...) -> CreateEntitiesBatchResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates multiple entities in a single request. Each entity is processed independently — a failure in one does not affect others.
+
+Returns an array of `{id, status}` objects in the same order as the input array.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi, CreateEntityRequest, AdditionalAttributes, CompanyAttributes
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.create_entities_batch(
+ entities=[
+ CreateEntityRequest(
+ name="OpenAI",
+ entity_type="company",
+ description="Artificial intelligence research company",
+ additional_attributes=AdditionalAttributes(
+ company_attributes=CompanyAttributes(
+ domain="openai.com",
+ key_persons=[
+ "Sam Altman"
+ ],
+ alternative_names=[
+ "Open AI"
+ ],
+ ),
+ ),
+ ),
+ CreateEntityRequest(
+ name="Stripe",
+ entity_type="company",
+ description="Online payment processing platform",
+ additional_attributes=AdditionalAttributes(
+ company_attributes=CompanyAttributes(
+ domain="stripe.com",
+ key_persons=[
+ "Patrick Collison",
+ "John Collison"
+ ],
+ ),
+ ),
+ )
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**entities:** `typing.List[CreateEntityRequest]`
+
+Array of entities to create. Each item follows the same schema
+as single entity creation.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.entities.get_entity(...) -> EntityResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a single entity by ID with all attributes and current status.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.get_entity(
+ entity_id="854198fa-f702-49db-a381-0427fa87f173",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**entity_id:** `str` — Unique entity identifier.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.entities.delete_entity(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Permanently deletes an entity. The entity is removed from all
+datasets and the search index. This operation cannot be undone.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.delete_entity(
+ entity_id="854198fa-f702-49db-a381-0427fa87f173",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**entity_id:** `str` — Unique entity identifier.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.entities.update_entity(...) -> EntityResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Updates one or more fields of an existing entity.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi, AdditionalAttributes, CompanyAttributes
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.entities.update_entity(
+ entity_id="854198fa-f702-49db-a381-0427fa87f173",
+ description="Updated description",
+ additional_attributes=AdditionalAttributes(
+ company_attributes=CompanyAttributes(
+ alternative_names=[
+ "NC",
+ "NewsCatcher API",
+ "NCA"
+ ],
+ ),
+ ),
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**entity_id:** `str` — Unique entity identifier.
+
+
+
+
+
+-
+
+**name:** `typing.Optional[str]` — Updated entity name.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — Updated description.
+
+
+
+
+
+-
+
+**additional_attributes:** `typing.Optional[AdditionalAttributes]`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Datasets
+client.datasets.list_datasets(...) -> DatasetListResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a paginated list of datasets belonging to the authenticated organization. Supports filtering by status and sorting by name, status, or creation date.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.list_datasets(
+ search="Portfolio",
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**page:** `typing.Optional[int]` — Page number to retrieve.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of datasets per page.
+
+
+
+
+
+-
+
+**search:** `typing.Optional[str]` — Filter datasets by name (case-insensitive substring match).
+
+
+
+
+
+-
+
+**latest_status:** `typing.Optional[DatasetStatus]` — Filter by dataset status.
+
+
+
+
+
+-
+
+**sort_by:** `typing.Optional[DatasetSortBy]`
+
+
+
+
+
+-
+
+**sort_order:** `typing.Optional[SortOrder]`
+
+
+
+
+
+-
+
+**ownership:** `typing.Optional[OwnershipFilter]`
+
+
+
+
+
+-
+
+**project_id:** `typing.Optional[str]` — Filter results to resources belonging to this project.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.create_dataset(...) -> DatasetResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates a new dataset from a list of existing entity IDs.
+
+If any of the provided entity IDs do not exist or do not belong to
+your organization, the request fails with `400`. All entity IDs must
+be valid before the dataset is created.
+
+To create a dataset and entities in one step, use the [`Create dataset from CSV`](https://www.newscatcherapi.com/docs/web-search-api/api-reference/datasets/create-dataset-from-csv)
+endpoint instead.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.create_dataset(
+ name="My Portfolio",
+ description="Companies in our investment portfolio",
+ entity_ids=[
+ "854198fa-f702-49db-a381-0427fa87f173",
+ "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**name:** `str` — Name for the dataset.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — Optional description.
+
+
+
+
+
+-
+
+**entity_ids:** `typing.Optional[typing.List[str]]` — IDs of existing entities to include in the dataset. All IDs must belong to the authenticated organization. If any ID is invalid or not found, the request fails with `400`.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.create_dataset_from_csv(...) -> CreateDatasetCsvResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates a new dataset by uploading a CSV file. Each row in the CSV becomes an entity. The `name` and `domain`columns are required; all other columns are optional.
+
+**CSV format:**
+```csv
+name,description,domain,alternative_names,key_persons
+NewsCatcher,"AI-powered news data provider",newscatcherapi.com,"NC;NewsCatcher API","Artem Bugara;Maksym Sugonyaka"
+OpenAI,"Artificial intelligence research company",openai.com,"Open AI","Sam Altman"
+```
+
+Use semicolons (`;`) to separate multiple values in `alternative_names` and `key_persons`. Rows with empty `name` are skipped and reported in `validation_report`.
+
+**Note**: The response shape differs from the JSON dataset creation endpoint: it returns `dataset_id` (not `id`) and includes a `validation_report` with details on skipped rows.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.create_dataset_from_csv(
+ file="example_file",
+ name="name",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**file:** `core.File` — The CSV file to upload.
+
+
+
+
+
+-
+
+**name:** `str` — Name for the new dataset.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — Optional description for the dataset.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.get_dataset(...) -> DatasetResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a single dataset by ID including entity count and current status.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.get_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.delete_dataset(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Permanently deletes a dataset. The entities within the dataset are
+not deleted — only the dataset itself. This operation cannot be
+undone.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.delete_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.update_dataset(...) -> DatasetResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Updates the name or description of a dataset.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.update_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+ name="My Portfolio (updated)",
+ description="Updated Q1 2026 watchlist",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**name:** `typing.Optional[str]` — Updated dataset name.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — Updated description.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.add_entities_to_dataset(...) -> ManageEntitiesResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Adds one or more existing entities to a dataset. Returns the number of entities added.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.add_entities_to_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+ entity_ids=[
+ "854198fa-f702-49db-a381-0427fa87f173"
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**request:** `DatasetEntityIdsRequest`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.remove_entities_from_dataset(...) -> ManageEntitiesResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Removes one or more entities from a dataset. The entities themselves are not deleted — they are only removed from this dataset. Returns the number of entities removed.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.remove_entities_from_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+ entity_ids=[
+ "854198fa-f702-49db-a381-0427fa87f173"
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**request:** `DatasetEntityIdsRequest`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.list_entities_in_dataset(...) -> DatasetEntityListResponse
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a paginated list of entities in a dataset. Supports filtering by status, entity type, and name search.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.list_entities_in_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+ page=1,
+ page_size=100,
+ search="OpenAI",
+ status="ready",
+ entity_type="company",
+ sort_by="created_at",
+ sort_order="desc",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**dataset_id:** `str` — Unique dataset identifier.
+
+
+
+
+
+-
+
+**page:** `typing.Optional[int]` — The page number to retrieve.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — The number of entities per page.
+
+
+
+
+
+-
+
+**search:** `typing.Optional[str]` — Filters entities by name using a case-insensitive substring match.
+
+
+
+
+
+-
+
+**status:** `typing.Optional[EntityStatus]`
+
+
+
+
+
+-
+
+**entity_type:** `typing.Optional[EntityType]`
+
+
+
+
+
+-
+
+**sort_by:** `typing.Optional[EntitySortBy]`
+
+
+
+
+
+-
+
+**sort_order:** `typing.Optional[SortOrder]`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.datasets.get_dataset_status_history(...) -> DatasetStatusHistoryResponse
+
+-
+
+#### 📝 Description
-
-**page_size:** `typing.Optional[int]` — Number of datasets per page.
-
-
-
-
-
-**search:** `typing.Optional[str]` — Filter datasets by name (case-insensitive substring match).
-
+Returns the full status change history for a dataset, ordered chronologically from oldest to newest.
+
+
+#### 🔌 Usage
+
-
-**latest_status:** `typing.Optional[DatasetStatus]` — Filter by dataset status.
-
-
-
-
-
-**sort_by:** `typing.Optional[DatasetSortBy]`
-
+```python
+from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall.environment import CatchAllApiEnvironment
+
+client = CatchAllApi(
+ api_key="",
+ environment=CatchAllApiEnvironment.DEFAULT,
+)
+
+client.datasets.get_dataset_status_history(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+)
+
+```
+
+
+#### ⚙️ Parameters
+
-
-**sort_order:** `typing.Optional[SortOrder]`
-
-
-
-
-
-**ownership:** `typing.Optional[OwnershipFilter]`
+**dataset_id:** `str` — Unique dataset identifier.
@@ -2164,7 +4238,7 @@ client.datasets.list_datasets(
-client.datasets.create_dataset(...) -> DatasetResponse
+client.datasets.upload_csv_to_dataset(...) -> UploadCsvToDatasetResponse
-
@@ -2176,14 +4250,9 @@ client.datasets.list_datasets(
-
-Creates a new dataset from a list of existing entity IDs.
-
-If any of the provided entity IDs do not exist or do not belong to
-your organization, the request fails with `400`. All entity IDs must
-be valid before the dataset is created.
+Appends new companies to an existing dataset by uploading a CSV file. Uses the same CSV format as the dataset creation endpoint.
-To create a dataset and entities in one step, use the [`Create dataset from CSV`](https://www.newscatcherapi.com/docs/web-search-api/api-reference/datasets/create-dataset-from-csv)
-endpoint instead.
+The response omits `dataset_name` compared to the create-from-CSV endpoint since the dataset already exists.
@@ -2206,13 +4275,9 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.create_dataset(
- name="My Portfolio",
- description="Companies in our investment portfolio",
- entity_ids=[
- "854198fa-f702-49db-a381-0427fa87f173",
- "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
- ],
+client.datasets.upload_csv_to_dataset(
+ dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+ file="example_file",
)
```
@@ -2229,15 +4294,7 @@ client.datasets.create_dataset(
-
-**name:** `str` — Name for the dataset.
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]` — Optional description.
+**dataset_id:** `str` — Unique dataset identifier.
@@ -2245,7 +4302,7 @@ client.datasets.create_dataset(
-
-**entity_ids:** `typing.Optional[typing.List[str]]` — IDs of existing entities to include in the dataset. All IDs must belong to the authenticated organization. If any ID is invalid or not found, the request fails with `400`.
+**file:** `core.File` — The CSV file to upload.
@@ -2265,7 +4322,8 @@ client.datasets.create_dataset(
-client.datasets.create_dataset_from_csv(...) -> CreateDatasetCsvResponse
+## Projects
+client.projects.list_projects(...) -> ProjectListResponseDto
-
@@ -2277,18 +4335,7 @@ client.datasets.create_dataset(
-
-Creates a new dataset by uploading a CSV file. Each row in the CSV becomes an entity. The `name` and `domain`columns are required; all other columns are optional.
-
-**CSV format:**
-```csv
-name,description,domain,alternative_names,key_persons
-NewsCatcher,"AI-powered news data provider",newscatcherapi.com,"NC;NewsCatcher API","Artem Bugara;Maksym Sugonyaka"
-OpenAI,"Artificial intelligence research company",openai.com,"Open AI","Sam Altman"
-```
-
-Use semicolons (`;`) to separate multiple values in `alternative_names` and `key_persons`. Rows with empty `name` are skipped and reported in `validation_report`.
-
-**Note**: The response shape differs from the JSON dataset creation endpoint: it returns `dataset_id` (not `id`) and includes a `validation_report` with details on skipped rows.
+Returns all projects visible to the authenticated user.
@@ -2311,9 +4358,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.create_dataset_from_csv(
- file="example_file",
- name="name",
+client.projects.list_projects(
+ search="M&A",
)
```
@@ -2330,7 +4376,7 @@ client.datasets.create_dataset_from_csv(
-
-**file:** `core.File` — The CSV file to upload.
+**page:** `typing.Optional[int]` — Page number to retrieve.
@@ -2338,7 +4384,7 @@ client.datasets.create_dataset_from_csv(
-
-**name:** `str` — Name for the new dataset.
+**page_size:** `typing.Optional[int]` — Number of records per page.
@@ -2346,7 +4392,15 @@ client.datasets.create_dataset_from_csv(
-
-**description:** `typing.Optional[str]` — Optional description for the dataset.
+**search:** `typing.Optional[str]` — Filter by project name (case-insensitive substring match).
+
+
+
+
+
+-
+
+**ownership:** `typing.Optional[OwnershipFilter]`
@@ -2366,7 +4420,7 @@ client.datasets.create_dataset_from_csv(
-client.datasets.get_dataset(...) -> DatasetResponse
+client.projects.create_project(...) -> CreateProjectResponseDto
-
@@ -2378,7 +4432,7 @@ client.datasets.create_dataset_from_csv(
-
-Returns a single dataset by ID including entity count and current status.
+Creates a new project.
@@ -2401,8 +4455,9 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.get_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+client.projects.create_project(
+ name="AI M&A Tracking",
+ description="Tracks AI-related M&A activity for our investment team.",
)
```
@@ -2419,7 +4474,15 @@ client.datasets.get_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
+**name:** `str` — Name for the project.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — Optional description.
@@ -2439,7 +4502,7 @@ client.datasets.get_dataset(
-client.datasets.delete_dataset(...)
+client.projects.get_project(...) -> ProjectResponseDto
-
@@ -2451,9 +4514,7 @@ client.datasets.get_dataset(
-
-Permanently deletes a dataset. The entities within the dataset are
-not deleted — only the dataset itself. This operation cannot be
-undone.
+Returns a single project by ID.
@@ -2476,8 +4537,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.delete_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+client.projects.get_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
```
@@ -2494,7 +4555,7 @@ client.datasets.delete_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
+**project_id:** `str` — Unique project identifier.
@@ -2514,7 +4575,7 @@ client.datasets.delete_dataset(
-client.datasets.update_dataset(...) -> DatasetResponse
+client.projects.delete_project(...)
-
@@ -2526,7 +4587,7 @@ client.datasets.delete_dataset(
-
-Updates the name or description of a dataset.
+Deletes a project. By default, assigned resources are unassigned but not deleted.
@@ -2549,10 +4610,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.update_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
- name="My Portfolio (updated)",
- description="Updated Q1 2026 watchlist",
+client.projects.delete_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
```
@@ -2569,15 +4628,7 @@ client.datasets.update_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]` — Updated dataset name.
+**project_id:** `str` — Unique project identifier.
@@ -2585,7 +4636,7 @@ client.datasets.update_dataset(
-
-**description:** `typing.Optional[str]` — Updated description.
+**delete_resources:** `typing.Optional[bool]` — If true, permanently deletes all resources (jobs, monitors, datasets) assigned to the project. If false, the project is deleted and its resources are unassigned but not deleted.
@@ -2605,7 +4656,7 @@ client.datasets.update_dataset(
-client.datasets.add_entities_to_dataset(...) -> ManageEntitiesResponse
+client.projects.update_project(...) -> UpdateProjectResponseDto
-
@@ -2617,7 +4668,7 @@ client.datasets.update_dataset(
-
-Adds one or more existing entities to a dataset. Returns the number of entities added.
+Updates the name or description of an existing project.
@@ -2640,11 +4691,9 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.add_entities_to_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
- entity_ids=[
- "854198fa-f702-49db-a381-0427fa87f173"
- ],
+client.projects.update_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ name="AI M&A Tracking (Q2 2026)",
)
```
@@ -2661,7 +4710,7 @@ client.datasets.add_entities_to_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
+**project_id:** `str` — Unique project identifier.
@@ -2669,7 +4718,15 @@ client.datasets.add_entities_to_dataset(
-
-**request:** `DatasetEntityIdsRequest`
+**name:** `typing.Optional[str]` — New name for the project.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — New description for the project.
@@ -2689,7 +4746,7 @@ client.datasets.add_entities_to_dataset(
-client.datasets.remove_entities_from_dataset(...) -> ManageEntitiesResponse
+client.projects.get_project_overview(...) -> ProjectOverviewResponseDto
-
@@ -2701,7 +4758,9 @@ client.datasets.add_entities_to_dataset(
-
-Removes one or more entities from a dataset. The entities themselves are not deleted — they are only removed from this dataset. Returns the number of entities removed.
+Returns resource counts for a project, grouped by type and status.
+
+For `jobs` and `monitors`, counts are broken down by status (for example, `completed`, `failed`). For `datasets` and `monitor_groups`, only a `total` count is returned.
@@ -2724,11 +4783,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.remove_entities_from_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
- entity_ids=[
- "854198fa-f702-49db-a381-0427fa87f173"
- ],
+client.projects.get_project_overview(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
```
@@ -2745,15 +4801,7 @@ client.datasets.remove_entities_from_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
-
-
-
-
-
--
-
-**request:** `DatasetEntityIdsRequest`
+**project_id:** `str` — Unique project identifier.
@@ -2773,7 +4821,7 @@ client.datasets.remove_entities_from_dataset(
-client.datasets.list_entities_in_dataset(...) -> DatasetEntityListResponse
+client.projects.list_project_resources(...) -> ProjectResourceListResponseDto
-
@@ -2785,7 +4833,7 @@ client.datasets.remove_entities_from_dataset(
-
-Returns a paginated list of entities in a dataset. Supports filtering by status, entity type, and name search.
+Returns all resources assigned to a project, with optional filtering by type.
@@ -2808,15 +4856,8 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.list_entities_in_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
- page=1,
- page_size=100,
- search="OpenAI",
- status="ready",
- entity_type="company",
- sort_by="created_at",
- sort_order="desc",
+client.projects.list_project_resources(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
```
@@ -2833,39 +4874,7 @@ client.datasets.list_entities_in_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
-
-
-
-
-
--
-
-**page:** `typing.Optional[int]` — The page number to retrieve.
-
-
-
-
-
--
-
-**page_size:** `typing.Optional[int]` — The number of entities per page.
-
-
-
-
-
--
-
-**search:** `typing.Optional[str]` — Filters entities by name using a case-insensitive substring match.
-
-
-
-
-
--
-
-**status:** `typing.Optional[EntityStatus]`
+**project_id:** `str` — Unique project identifier.
@@ -2873,7 +4882,7 @@ client.datasets.list_entities_in_dataset(
-
-**entity_type:** `typing.Optional[EntityType]`
+**resource_type:** `typing.Optional[ProjectResourceType]`
@@ -2881,7 +4890,7 @@ client.datasets.list_entities_in_dataset(
-
-**sort_by:** `typing.Optional[EntitySortBy]`
+**page:** `typing.Optional[int]` — Page number to retrieve.
@@ -2889,7 +4898,7 @@ client.datasets.list_entities_in_dataset(
-
-**sort_order:** `typing.Optional[SortOrder]`
+**page_size:** `typing.Optional[int]` — Number of records per page.
@@ -2909,7 +4918,7 @@ client.datasets.list_entities_in_dataset(
-client.datasets.get_dataset_status_history(...) -> DatasetStatusHistoryResponse
+client.projects.add_resource_to_project(...) -> AddResourceResponseDto
-
@@ -2921,7 +4930,7 @@ client.datasets.list_entities_in_dataset(
-
-Returns the full status change history for a dataset, ordered chronologically from oldest to newest.
+Assigns one or more existing resources to a project in a single request.
@@ -2936,7 +4945,7 @@ Returns the full status change history for a dataset, ordered chronologically fr
-
```python
-from newscatcher_catchall import CatchAllApi
+from newscatcher_catchall import CatchAllApi, ResourceItemDto
from newscatcher_catchall.environment import CatchAllApiEnvironment
client = CatchAllApi(
@@ -2944,8 +4953,14 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.get_dataset_status_history(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
+client.projects.add_resource_to_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resources=[
+ ResourceItemDto(
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
+ )
+ ],
)
```
@@ -2962,7 +4977,15 @@ client.datasets.get_dataset_status_history(
-
-**dataset_id:** `str` — Unique dataset identifier.
+**project_id:** `str` — Unique project identifier.
+
+
+
+
+
+-
+
+**resources:** `typing.List[ResourceItemDto]` — Resources to assign to the project.
@@ -2982,7 +5005,7 @@ client.datasets.get_dataset_status_history(
-client.datasets.upload_csv_to_dataset(...) -> UploadCsvToDatasetResponse
+client.projects.remove_resource_from_project(...) -> RemoveResourceResponseDto
-
@@ -2994,9 +5017,8 @@ client.datasets.get_dataset_status_history(
-
-Appends new companies to an existing dataset by uploading a CSV file. Uses the same CSV format as the dataset creation endpoint.
-
-The response omits `dataset_name` compared to the create-from-CSV endpoint since the dataset already exists.
+Removes a resource from a project. The resource itself is not
+deleted — it becomes unassigned and continues to exist.
@@ -3019,9 +5041,10 @@ client = CatchAllApi(
environment=CatchAllApiEnvironment.DEFAULT,
)
-client.datasets.upload_csv_to_dataset(
- dataset_id="ccabb755-afc2-4047-b84c-78d1f23d49b2",
- file="example_file",
+client.projects.remove_resource_from_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
)
```
@@ -3038,7 +5061,7 @@ client.datasets.upload_csv_to_dataset(
-
-**dataset_id:** `str` — Unique dataset identifier.
+**project_id:** `str` — Unique project identifier.
@@ -3046,7 +5069,15 @@ client.datasets.upload_csv_to_dataset(
-
-**file:** `core.File` — The CSV file to upload.
+**resource_type:** `ProjectResourceType`
+
+
+
+
+
+-
+
+**resource_id:** `str` — ID of the resource to remove.
diff --git a/src/newscatcher_catchall/__init__.py b/src/newscatcher_catchall/__init__.py
index 45f2c01..b59b54e 100644
--- a/src/newscatcher_catchall/__init__.py
+++ b/src/newscatcher_catchall/__init__.py
@@ -7,10 +7,15 @@
if typing.TYPE_CHECKING:
from .types import (
+ AddResourceResponseDto,
AdditionalAttributes,
+ ApiKeyAuthDto,
+ AssignWebhookResourceResponseDto,
BaseRecord,
BaseRecordEnrichment,
BaseRecordEnrichmentEnrichmentConfidence,
+ BasicAuthDto,
+ BearerAuthDto,
Citation,
CompanyAttributes,
CompanyEnrichmentOutput,
@@ -24,6 +29,8 @@
CreateEntityRequest,
CreateEntityResponse,
CreateMonitorResponseDto,
+ CreateProjectResponseDto,
+ CreateWebhookResponseDto,
DatasetEntityIdsRequest,
DatasetEntityListResponse,
DatasetListResponse,
@@ -34,6 +41,10 @@
DatasetStatusHistoryResponse,
DeleteJobResponseDto,
DeleteMonitorResponseDto,
+ DeliveryHistoryItemDto,
+ DeliveryHistoryResponseDto,
+ DeliveryMode,
+ DeliveryStatus,
EndDate,
EnrichmentSchema,
EnrichmentType,
@@ -46,12 +57,18 @@
EntityValidationErrorBody,
Error,
GetPlanLimitsResponseDto,
+ GetWebhookResponseDto,
+ HttpMethod,
InitializeResponseDto,
+ IssueType,
JobStep,
Limit,
ListMonitorsResponseDto,
ListUserJobsResponseDto,
+ ListWebhookResourcesResponseDto,
+ ListWebhooksResponseDto,
ManageEntitiesResponse,
+ MappableResourceType,
MonitorCitation,
MonitorJobItem,
MonitorListItemDto,
@@ -61,6 +78,15 @@
MonitorStatusHistoryResponseDto,
OwnershipFilter,
PlanFeature,
+ ProjectListResponseDto,
+ ProjectOverviewCountsDto,
+ ProjectOverviewResponseDto,
+ ProjectOverviewResponseDtoOverview,
+ ProjectResourceDto,
+ ProjectResourceListResponseDto,
+ ProjectResourceType,
+ ProjectResponseDto,
+ ProjectSummaryDto,
PublicJobStatus,
PullJobResponseDto,
PullJobResponseDtoDateRange,
@@ -68,8 +94,12 @@
PullMonitorResponseDto,
PullMonitorResponseDtoRunInfo,
Query,
+ QueryStatus,
Record,
ReferenceJob,
+ RemoveResourceResponseDto,
+ ResourceItemDto,
+ ResourceResultDto,
SharingInfo,
SharingInfoPermission,
SkippedRow,
@@ -77,10 +107,15 @@
StartDate,
StatusResponseDto,
SubmitResponseDto,
+ Suggestion,
+ TestWebhookResponseDto,
UpdateMonitorResponseDto,
+ UpdateProjectResponseDto,
+ UpdateWebhookResponseDto,
UploadCsvToDatasetResponse,
UserJob,
UserJobMode,
+ ValidateQueryResponseDto,
ValidationErrorDetail,
ValidationErrorDetailLocItem,
ValidationErrorResponse,
@@ -89,9 +124,12 @@
WebhookDto,
WebhookDtoMethod,
WebhookPayload,
+ WebhookResourceMappingResponseDto,
+ WebhookResponseDto,
+ WebhookType,
)
from .errors import BadRequestError, ForbiddenError, NotFoundError, UnauthorizedError, UnprocessableEntityError
- from . import datasets, entities, jobs, meta, monitors
+ from . import datasets, entities, jobs, meta, monitors, projects, webhooks
from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient
from .client import AsyncCatchAllApi, CatchAllApi
from .environment import CatchAllApiEnvironment
@@ -105,13 +143,28 @@
ListMonitorJobsResponseSortOrder,
)
from .version import __version__
+ from .webhooks import (
+ CreateWebhookRequestDtoAuth,
+ CreateWebhookRequestDtoAuth_ApiKey,
+ CreateWebhookRequestDtoAuth_Basic,
+ CreateWebhookRequestDtoAuth_Bearer,
+ UpdateWebhookRequestDtoAuth,
+ UpdateWebhookRequestDtoAuth_ApiKey,
+ UpdateWebhookRequestDtoAuth_Basic,
+ UpdateWebhookRequestDtoAuth_Bearer,
+ )
_dynamic_imports: typing.Dict[str, str] = {
+ "AddResourceResponseDto": ".types",
"AdditionalAttributes": ".types",
+ "ApiKeyAuthDto": ".types",
+ "AssignWebhookResourceResponseDto": ".types",
"AsyncCatchAllApi": ".client",
"BadRequestError": ".errors",
"BaseRecord": ".types",
"BaseRecordEnrichment": ".types",
"BaseRecordEnrichmentEnrichmentConfidence": ".types",
+ "BasicAuthDto": ".types",
+ "BearerAuthDto": ".types",
"CatchAllApi": ".client",
"CatchAllApiEnvironment": ".environment",
"Citation": ".types",
@@ -127,6 +180,12 @@
"CreateEntityRequest": ".types",
"CreateEntityResponse": ".types",
"CreateMonitorResponseDto": ".types",
+ "CreateProjectResponseDto": ".types",
+ "CreateWebhookRequestDtoAuth": ".webhooks",
+ "CreateWebhookRequestDtoAuth_ApiKey": ".webhooks",
+ "CreateWebhookRequestDtoAuth_Basic": ".webhooks",
+ "CreateWebhookRequestDtoAuth_Bearer": ".webhooks",
+ "CreateWebhookResponseDto": ".types",
"DatasetEntityIdsRequest": ".types",
"DatasetEntityListResponse": ".types",
"DatasetListResponse": ".types",
@@ -139,6 +198,10 @@
"DefaultAsyncHttpxClient": "._default_clients",
"DeleteJobResponseDto": ".types",
"DeleteMonitorResponseDto": ".types",
+ "DeliveryHistoryItemDto": ".types",
+ "DeliveryHistoryResponseDto": ".types",
+ "DeliveryMode": ".types",
+ "DeliveryStatus": ".types",
"DisableMonitorResponse": ".monitors",
"EnableMonitorResponse": ".monitors",
"EndDate": ".types",
@@ -155,8 +218,11 @@
"ForbiddenError": ".errors",
"GetPlanLimitsResponseDto": ".types",
"GetVersionResponse": ".meta",
+ "GetWebhookResponseDto": ".types",
"HealthCheckResponse": ".meta",
+ "HttpMethod": ".types",
"InitializeResponseDto": ".types",
+ "IssueType": ".types",
"JobStep": ".types",
"Limit": ".types",
"ListMonitorJobsRequestSort": ".monitors",
@@ -164,7 +230,10 @@
"ListMonitorJobsResponseSortOrder": ".monitors",
"ListMonitorsResponseDto": ".types",
"ListUserJobsResponseDto": ".types",
+ "ListWebhookResourcesResponseDto": ".types",
+ "ListWebhooksResponseDto": ".types",
"ManageEntitiesResponse": ".types",
+ "MappableResourceType": ".types",
"MonitorCitation": ".types",
"MonitorJobItem": ".types",
"MonitorListItemDto": ".types",
@@ -175,6 +244,15 @@
"NotFoundError": ".errors",
"OwnershipFilter": ".types",
"PlanFeature": ".types",
+ "ProjectListResponseDto": ".types",
+ "ProjectOverviewCountsDto": ".types",
+ "ProjectOverviewResponseDto": ".types",
+ "ProjectOverviewResponseDtoOverview": ".types",
+ "ProjectResourceDto": ".types",
+ "ProjectResourceListResponseDto": ".types",
+ "ProjectResourceType": ".types",
+ "ProjectResponseDto": ".types",
+ "ProjectSummaryDto": ".types",
"PublicJobStatus": ".types",
"PullJobResponseDto": ".types",
"PullJobResponseDtoDateRange": ".types",
@@ -182,8 +260,12 @@
"PullMonitorResponseDto": ".types",
"PullMonitorResponseDtoRunInfo": ".types",
"Query": ".types",
+ "QueryStatus": ".types",
"Record": ".types",
"ReferenceJob": ".types",
+ "RemoveResourceResponseDto": ".types",
+ "ResourceItemDto": ".types",
+ "ResourceResultDto": ".types",
"SharingInfo": ".types",
"SharingInfoPermission": ".types",
"SkippedRow": ".types",
@@ -192,12 +274,21 @@
"StatusResponseDto": ".types",
"SubmitRequestDtoMode": ".jobs",
"SubmitResponseDto": ".types",
+ "Suggestion": ".types",
+ "TestWebhookResponseDto": ".types",
"UnauthorizedError": ".errors",
"UnprocessableEntityError": ".errors",
"UpdateMonitorResponseDto": ".types",
+ "UpdateProjectResponseDto": ".types",
+ "UpdateWebhookRequestDtoAuth": ".webhooks",
+ "UpdateWebhookRequestDtoAuth_ApiKey": ".webhooks",
+ "UpdateWebhookRequestDtoAuth_Basic": ".webhooks",
+ "UpdateWebhookRequestDtoAuth_Bearer": ".webhooks",
+ "UpdateWebhookResponseDto": ".types",
"UploadCsvToDatasetResponse": ".types",
"UserJob": ".types",
"UserJobMode": ".types",
+ "ValidateQueryResponseDto": ".types",
"ValidationErrorDetail": ".types",
"ValidationErrorDetailLocItem": ".types",
"ValidationErrorResponse": ".types",
@@ -206,12 +297,17 @@
"WebhookDto": ".types",
"WebhookDtoMethod": ".types",
"WebhookPayload": ".types",
+ "WebhookResourceMappingResponseDto": ".types",
+ "WebhookResponseDto": ".types",
+ "WebhookType": ".types",
"__version__": ".version",
"datasets": ".datasets",
"entities": ".entities",
"jobs": ".jobs",
"meta": ".meta",
"monitors": ".monitors",
+ "projects": ".projects",
+ "webhooks": ".webhooks",
}
@@ -237,12 +333,17 @@ def __dir__():
__all__ = [
+ "AddResourceResponseDto",
"AdditionalAttributes",
+ "ApiKeyAuthDto",
+ "AssignWebhookResourceResponseDto",
"AsyncCatchAllApi",
"BadRequestError",
"BaseRecord",
"BaseRecordEnrichment",
"BaseRecordEnrichmentEnrichmentConfidence",
+ "BasicAuthDto",
+ "BearerAuthDto",
"CatchAllApi",
"CatchAllApiEnvironment",
"Citation",
@@ -258,6 +359,12 @@ def __dir__():
"CreateEntityRequest",
"CreateEntityResponse",
"CreateMonitorResponseDto",
+ "CreateProjectResponseDto",
+ "CreateWebhookRequestDtoAuth",
+ "CreateWebhookRequestDtoAuth_ApiKey",
+ "CreateWebhookRequestDtoAuth_Basic",
+ "CreateWebhookRequestDtoAuth_Bearer",
+ "CreateWebhookResponseDto",
"DatasetEntityIdsRequest",
"DatasetEntityListResponse",
"DatasetListResponse",
@@ -270,6 +377,10 @@ def __dir__():
"DefaultAsyncHttpxClient",
"DeleteJobResponseDto",
"DeleteMonitorResponseDto",
+ "DeliveryHistoryItemDto",
+ "DeliveryHistoryResponseDto",
+ "DeliveryMode",
+ "DeliveryStatus",
"DisableMonitorResponse",
"EnableMonitorResponse",
"EndDate",
@@ -286,8 +397,11 @@ def __dir__():
"ForbiddenError",
"GetPlanLimitsResponseDto",
"GetVersionResponse",
+ "GetWebhookResponseDto",
"HealthCheckResponse",
+ "HttpMethod",
"InitializeResponseDto",
+ "IssueType",
"JobStep",
"Limit",
"ListMonitorJobsRequestSort",
@@ -295,7 +409,10 @@ def __dir__():
"ListMonitorJobsResponseSortOrder",
"ListMonitorsResponseDto",
"ListUserJobsResponseDto",
+ "ListWebhookResourcesResponseDto",
+ "ListWebhooksResponseDto",
"ManageEntitiesResponse",
+ "MappableResourceType",
"MonitorCitation",
"MonitorJobItem",
"MonitorListItemDto",
@@ -306,6 +423,15 @@ def __dir__():
"NotFoundError",
"OwnershipFilter",
"PlanFeature",
+ "ProjectListResponseDto",
+ "ProjectOverviewCountsDto",
+ "ProjectOverviewResponseDto",
+ "ProjectOverviewResponseDtoOverview",
+ "ProjectResourceDto",
+ "ProjectResourceListResponseDto",
+ "ProjectResourceType",
+ "ProjectResponseDto",
+ "ProjectSummaryDto",
"PublicJobStatus",
"PullJobResponseDto",
"PullJobResponseDtoDateRange",
@@ -313,8 +439,12 @@ def __dir__():
"PullMonitorResponseDto",
"PullMonitorResponseDtoRunInfo",
"Query",
+ "QueryStatus",
"Record",
"ReferenceJob",
+ "RemoveResourceResponseDto",
+ "ResourceItemDto",
+ "ResourceResultDto",
"SharingInfo",
"SharingInfoPermission",
"SkippedRow",
@@ -323,12 +453,21 @@ def __dir__():
"StatusResponseDto",
"SubmitRequestDtoMode",
"SubmitResponseDto",
+ "Suggestion",
+ "TestWebhookResponseDto",
"UnauthorizedError",
"UnprocessableEntityError",
"UpdateMonitorResponseDto",
+ "UpdateProjectResponseDto",
+ "UpdateWebhookRequestDtoAuth",
+ "UpdateWebhookRequestDtoAuth_ApiKey",
+ "UpdateWebhookRequestDtoAuth_Basic",
+ "UpdateWebhookRequestDtoAuth_Bearer",
+ "UpdateWebhookResponseDto",
"UploadCsvToDatasetResponse",
"UserJob",
"UserJobMode",
+ "ValidateQueryResponseDto",
"ValidationErrorDetail",
"ValidationErrorDetailLocItem",
"ValidationErrorResponse",
@@ -337,10 +476,15 @@ def __dir__():
"WebhookDto",
"WebhookDtoMethod",
"WebhookPayload",
+ "WebhookResourceMappingResponseDto",
+ "WebhookResponseDto",
+ "WebhookType",
"__version__",
"datasets",
"entities",
"jobs",
"meta",
"monitors",
+ "projects",
+ "webhooks",
]
diff --git a/src/newscatcher_catchall/client.py b/src/newscatcher_catchall/client.py
index c05ab55..b7f052b 100644
--- a/src/newscatcher_catchall/client.py
+++ b/src/newscatcher_catchall/client.py
@@ -15,6 +15,8 @@
from .jobs.client import AsyncJobsClient, JobsClient
from .meta.client import AsyncMetaClient, MetaClient
from .monitors.client import AsyncMonitorsClient, MonitorsClient
+ from .projects.client import AsyncProjectsClient, ProjectsClient
+ from .webhooks.client import AsyncWebhooksClient, WebhooksClient
class CatchAllApi:
@@ -95,8 +97,10 @@ def __init__(
)
self._jobs: typing.Optional[JobsClient] = None
self._monitors: typing.Optional[MonitorsClient] = None
+ self._webhooks: typing.Optional[WebhooksClient] = None
self._entities: typing.Optional[EntitiesClient] = None
self._datasets: typing.Optional[DatasetsClient] = None
+ self._projects: typing.Optional[ProjectsClient] = None
self._meta: typing.Optional[MetaClient] = None
@property
@@ -115,6 +119,14 @@ def monitors(self):
self._monitors = MonitorsClient(client_wrapper=self._client_wrapper)
return self._monitors
+ @property
+ def webhooks(self):
+ if self._webhooks is None:
+ from .webhooks.client import WebhooksClient # noqa: E402
+
+ self._webhooks = WebhooksClient(client_wrapper=self._client_wrapper)
+ return self._webhooks
+
@property
def entities(self):
if self._entities is None:
@@ -131,6 +143,14 @@ def datasets(self):
self._datasets = DatasetsClient(client_wrapper=self._client_wrapper)
return self._datasets
+ @property
+ def projects(self):
+ if self._projects is None:
+ from .projects.client import ProjectsClient # noqa: E402
+
+ self._projects = ProjectsClient(client_wrapper=self._client_wrapper)
+ return self._projects
+
@property
def meta(self):
if self._meta is None:
@@ -234,8 +254,10 @@ def __init__(
)
self._jobs: typing.Optional[AsyncJobsClient] = None
self._monitors: typing.Optional[AsyncMonitorsClient] = None
+ self._webhooks: typing.Optional[AsyncWebhooksClient] = None
self._entities: typing.Optional[AsyncEntitiesClient] = None
self._datasets: typing.Optional[AsyncDatasetsClient] = None
+ self._projects: typing.Optional[AsyncProjectsClient] = None
self._meta: typing.Optional[AsyncMetaClient] = None
@property
@@ -254,6 +276,14 @@ def monitors(self):
self._monitors = AsyncMonitorsClient(client_wrapper=self._client_wrapper)
return self._monitors
+ @property
+ def webhooks(self):
+ if self._webhooks is None:
+ from .webhooks.client import AsyncWebhooksClient # noqa: E402
+
+ self._webhooks = AsyncWebhooksClient(client_wrapper=self._client_wrapper)
+ return self._webhooks
+
@property
def entities(self):
if self._entities is None:
@@ -270,6 +300,14 @@ def datasets(self):
self._datasets = AsyncDatasetsClient(client_wrapper=self._client_wrapper)
return self._datasets
+ @property
+ def projects(self):
+ if self._projects is None:
+ from .projects.client import AsyncProjectsClient # noqa: E402
+
+ self._projects = AsyncProjectsClient(client_wrapper=self._client_wrapper)
+ return self._projects
+
@property
def meta(self):
if self._meta is None:
diff --git a/src/newscatcher_catchall/core/client_wrapper.py b/src/newscatcher_catchall/core/client_wrapper.py
index 3727234..e54e12d 100644
--- a/src/newscatcher_catchall/core/client_wrapper.py
+++ b/src/newscatcher_catchall/core/client_wrapper.py
@@ -29,12 +29,12 @@ def get_headers(self) -> typing.Dict[str, str]:
import platform
headers: typing.Dict[str, str] = {
- "User-Agent": "newscatcher-catchall-sdk/2.0.0",
+ "User-Agent": "newscatcher-catchall-sdk/3.0.0",
"X-Fern-Language": "Python",
"X-Fern-Runtime": f"python/{platform.python_version()}",
"X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}",
"X-Fern-SDK-Name": "newscatcher-catchall-sdk",
- "X-Fern-SDK-Version": "2.0.0",
+ "X-Fern-SDK-Version": "3.0.0",
**(self.get_custom_headers() or {}),
}
headers["x-api-key"] = self.api_key
diff --git a/src/newscatcher_catchall/datasets/client.py b/src/newscatcher_catchall/datasets/client.py
index b4e150f..a3858b3 100644
--- a/src/newscatcher_catchall/datasets/client.py
+++ b/src/newscatcher_catchall/datasets/client.py
@@ -50,6 +50,7 @@ def list_datasets(
sort_by: typing.Optional[DatasetSortBy] = None,
sort_order: typing.Optional[SortOrder] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> DatasetListResponse:
"""
@@ -75,6 +76,9 @@ def list_datasets(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -92,6 +96,7 @@ def list_datasets(
)
client.datasets.list_datasets(
search="Portfolio",
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
"""
_response = self._raw_client.list_datasets(
@@ -102,6 +107,7 @@ def list_datasets(
sort_by=sort_by,
sort_order=sort_order,
ownership=ownership,
+ project_id=project_id,
request_options=request_options,
)
return _response.data
@@ -594,6 +600,7 @@ async def list_datasets(
sort_by: typing.Optional[DatasetSortBy] = None,
sort_order: typing.Optional[SortOrder] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> DatasetListResponse:
"""
@@ -619,6 +626,9 @@ async def list_datasets(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -641,6 +651,7 @@ async def list_datasets(
async def main() -> None:
await client.datasets.list_datasets(
search="Portfolio",
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
)
@@ -654,6 +665,7 @@ async def main() -> None:
sort_by=sort_by,
sort_order=sort_order,
ownership=ownership,
+ project_id=project_id,
request_options=request_options,
)
return _response.data
diff --git a/src/newscatcher_catchall/datasets/raw_client.py b/src/newscatcher_catchall/datasets/raw_client.py
index 84d3810..a69ef87 100644
--- a/src/newscatcher_catchall/datasets/raw_client.py
+++ b/src/newscatcher_catchall/datasets/raw_client.py
@@ -51,6 +51,7 @@ def list_datasets(
sort_by: typing.Optional[DatasetSortBy] = None,
sort_order: typing.Optional[SortOrder] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[DatasetListResponse]:
"""
@@ -76,6 +77,9 @@ def list_datasets(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -95,6 +99,7 @@ def list_datasets(
"sort_by": sort_by,
"sort_order": sort_order,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
@@ -1009,6 +1014,7 @@ async def list_datasets(
sort_by: typing.Optional[DatasetSortBy] = None,
sort_order: typing.Optional[SortOrder] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[DatasetListResponse]:
"""
@@ -1034,6 +1040,9 @@ async def list_datasets(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -1053,6 +1062,7 @@ async def list_datasets(
"sort_by": sort_by,
"sort_order": sort_order,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
diff --git a/src/newscatcher_catchall/entities/raw_client.py b/src/newscatcher_catchall/entities/raw_client.py
index b97c093..64759f3 100644
--- a/src/newscatcher_catchall/entities/raw_client.py
+++ b/src/newscatcher_catchall/entities/raw_client.py
@@ -169,9 +169,6 @@ def create_entity(
object_=additional_attributes, annotation=AdditionalAttributes, direction="write"
),
},
- headers={
- "content-type": "application/json",
- },
request_options=request_options,
omit=OMIT,
)
@@ -656,9 +653,6 @@ async def create_entity(
object_=additional_attributes, annotation=AdditionalAttributes, direction="write"
),
},
- headers={
- "content-type": "application/json",
- },
request_options=request_options,
omit=OMIT,
)
diff --git a/src/newscatcher_catchall/jobs/client.py b/src/newscatcher_catchall/jobs/client.py
index 3138c9f..b0e7420 100644
--- a/src/newscatcher_catchall/jobs/client.py
+++ b/src/newscatcher_catchall/jobs/client.py
@@ -18,6 +18,7 @@
from ..types.start_date import StartDate
from ..types.status_response_dto import StatusResponseDto
from ..types.submit_response_dto import SubmitResponseDto
+from ..types.validate_query_response_dto import ValidateQueryResponseDto
from ..types.validator_schema import ValidatorSchema
from .raw_client import AsyncRawJobsClient, RawJobsClient
from .types.submit_request_dto_mode import SubmitRequestDtoMode
@@ -48,6 +49,7 @@ def get_user_jobs(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ListUserJobsResponseDto:
"""
@@ -66,6 +68,9 @@ def get_user_jobs(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -81,13 +86,55 @@ def get_user_jobs(
client = CatchAllApi(
api_key="YOUR_API_KEY",
)
- client.jobs.get_user_jobs()
+ client.jobs.get_user_jobs(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
"""
_response = self._raw_client.get_user_jobs(
- page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ page=page,
+ page_size=page_size,
+ search=search,
+ ownership=ownership,
+ project_id=project_id,
+ request_options=request_options,
)
return _response.data
+ def validate_query(
+ self, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> ValidateQueryResponseDto:
+ """
+ Checks whether a query is well-formed and likely to produce good results before submitting a job.
+
+ Returns a quality assessment with a status level, identified issues, and actionable suggestions.
+
+ Parameters
+ ----------
+ query : str
+ Plain text query to validate.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ValidateQueryResponseDto
+ Query validation result.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.jobs.validate_query(
+ query="Series B funding rounds for SaaS startups",
+ )
+ """
+ _response = self._raw_client.validate_query(query=query, request_options=request_options)
+ return _response.data
+
def initialize(
self,
*,
@@ -140,6 +187,8 @@ def create_job(
mode: typing.Optional[SubmitRequestDtoMode] = OMIT,
connected_dataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
ed_score_min: typing.Optional[int] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> SubmitResponseDto:
"""
@@ -183,6 +232,12 @@ def create_job(
Only valid when `connected_dataset_ids` is set; otherwise ignored. Records where no connected entity meets the threshold are excluded entirely.
+ project_id : typing.Optional[str]
+ Project to assign this job to. The job appears in the project's resource list immediately after submission.
+
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of webhooks to notify when the job completes. Maximum 5 per job.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -224,6 +279,8 @@ def create_job(
mode=mode,
connected_dataset_ids=connected_dataset_ids,
ed_score_min=ed_score_min,
+ project_id=project_id,
+ webhook_ids=webhook_ids,
request_options=request_options,
)
return _response.data
@@ -408,6 +465,7 @@ async def get_user_jobs(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ListUserJobsResponseDto:
"""
@@ -426,6 +484,9 @@ async def get_user_jobs(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -446,14 +507,64 @@ async def get_user_jobs(
async def main() -> None:
- await client.jobs.get_user_jobs()
+ await client.jobs.get_user_jobs(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
asyncio.run(main())
"""
_response = await self._raw_client.get_user_jobs(
- page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ page=page,
+ page_size=page_size,
+ search=search,
+ ownership=ownership,
+ project_id=project_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def validate_query(
+ self, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> ValidateQueryResponseDto:
+ """
+ Checks whether a query is well-formed and likely to produce good results before submitting a job.
+
+ Returns a quality assessment with a status level, identified issues, and actionable suggestions.
+
+ Parameters
+ ----------
+ query : str
+ Plain text query to validate.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ValidateQueryResponseDto
+ Query validation result.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
)
+
+
+ async def main() -> None:
+ await client.jobs.validate_query(
+ query="Series B funding rounds for SaaS startups",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.validate_query(query=query, request_options=request_options)
return _response.data
async def initialize(
@@ -516,6 +627,8 @@ async def create_job(
mode: typing.Optional[SubmitRequestDtoMode] = OMIT,
connected_dataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
ed_score_min: typing.Optional[int] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> SubmitResponseDto:
"""
@@ -559,6 +672,12 @@ async def create_job(
Only valid when `connected_dataset_ids` is set; otherwise ignored. Records where no connected entity meets the threshold are excluded entirely.
+ project_id : typing.Optional[str]
+ Project to assign this job to. The job appears in the project's resource list immediately after submission.
+
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of webhooks to notify when the job completes. Maximum 5 per job.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -607,6 +726,8 @@ async def main() -> None:
mode=mode,
connected_dataset_ids=connected_dataset_ids,
ed_score_min=ed_score_min,
+ project_id=project_id,
+ webhook_ids=webhook_ids,
request_options=request_options,
)
return _response.data
diff --git a/src/newscatcher_catchall/jobs/raw_client.py b/src/newscatcher_catchall/jobs/raw_client.py
index 396d409..8a79960 100644
--- a/src/newscatcher_catchall/jobs/raw_client.py
+++ b/src/newscatcher_catchall/jobs/raw_client.py
@@ -31,6 +31,7 @@
from ..types.start_date import StartDate
from ..types.status_response_dto import StatusResponseDto
from ..types.submit_response_dto import SubmitResponseDto
+from ..types.validate_query_response_dto import ValidateQueryResponseDto
from ..types.validation_error_response import ValidationErrorResponse
from ..types.validator_schema import ValidatorSchema
from .types.submit_request_dto_mode import SubmitRequestDtoMode
@@ -51,6 +52,7 @@ def get_user_jobs(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[ListUserJobsResponseDto]:
"""
@@ -69,6 +71,9 @@ def get_user_jobs(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -85,6 +90,7 @@ def get_user_jobs(
"page_size": page_size,
"search": search,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
@@ -118,6 +124,80 @@ def get_user_jobs(
)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+ def validate_query(
+ self, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[ValidateQueryResponseDto]:
+ """
+ Checks whether a query is well-formed and likely to produce good results before submitting a job.
+
+ Returns a quality assessment with a status level, identified issues, and actionable suggestions.
+
+ Parameters
+ ----------
+ query : str
+ Plain text query to validate.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ValidateQueryResponseDto]
+ Query validation result.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/validate",
+ method="POST",
+ json={
+ "query": query,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ValidateQueryResponseDto,
+ parse_obj_as(
+ type_=ValidateQueryResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
def initialize(
self,
*,
@@ -209,6 +289,8 @@ def create_job(
mode: typing.Optional[SubmitRequestDtoMode] = OMIT,
connected_dataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
ed_score_min: typing.Optional[int] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[SubmitResponseDto]:
"""
@@ -252,6 +334,12 @@ def create_job(
Only valid when `connected_dataset_ids` is set; otherwise ignored. Records where no connected entity meets the threshold are excluded entirely.
+ project_id : typing.Optional[str]
+ Project to assign this job to. The job appears in the project's resource list immediately after submission.
+
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of webhooks to notify when the job completes. Maximum 5 per job.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -278,6 +366,8 @@ def create_job(
"mode": mode,
"connected_dataset_ids": connected_dataset_ids,
"ed_score_min": ed_score_min,
+ "project_id": project_id,
+ "webhook_ids": webhook_ids,
},
headers={
"content-type": "application/json",
@@ -654,6 +744,7 @@ async def get_user_jobs(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[ListUserJobsResponseDto]:
"""
@@ -672,6 +763,9 @@ async def get_user_jobs(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -688,6 +782,7 @@ async def get_user_jobs(
"page_size": page_size,
"search": search,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
@@ -721,6 +816,80 @@ async def get_user_jobs(
)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+ async def validate_query(
+ self, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[ValidateQueryResponseDto]:
+ """
+ Checks whether a query is well-formed and likely to produce good results before submitting a job.
+
+ Returns a quality assessment with a status level, identified issues, and actionable suggestions.
+
+ Parameters
+ ----------
+ query : str
+ Plain text query to validate.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ValidateQueryResponseDto]
+ Query validation result.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/validate",
+ method="POST",
+ json={
+ "query": query,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ValidateQueryResponseDto,
+ parse_obj_as(
+ type_=ValidateQueryResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
async def initialize(
self,
*,
@@ -812,6 +981,8 @@ async def create_job(
mode: typing.Optional[SubmitRequestDtoMode] = OMIT,
connected_dataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
ed_score_min: typing.Optional[int] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[SubmitResponseDto]:
"""
@@ -855,6 +1026,12 @@ async def create_job(
Only valid when `connected_dataset_ids` is set; otherwise ignored. Records where no connected entity meets the threshold are excluded entirely.
+ project_id : typing.Optional[str]
+ Project to assign this job to. The job appears in the project's resource list immediately after submission.
+
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of webhooks to notify when the job completes. Maximum 5 per job.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -881,6 +1058,8 @@ async def create_job(
"mode": mode,
"connected_dataset_ids": connected_dataset_ids,
"ed_score_min": ed_score_min,
+ "project_id": project_id,
+ "webhook_ids": webhook_ids,
},
headers={
"content-type": "application/json",
diff --git a/src/newscatcher_catchall/monitors/client.py b/src/newscatcher_catchall/monitors/client.py
index 7b1bfe8..37e5bdc 100644
--- a/src/newscatcher_catchall/monitors/client.py
+++ b/src/newscatcher_catchall/monitors/client.py
@@ -11,7 +11,6 @@
from ..types.ownership_filter import OwnershipFilter
from ..types.pull_monitor_response_dto import PullMonitorResponseDto
from ..types.update_monitor_response_dto import UpdateMonitorResponseDto
-from ..types.webhook_dto import WebhookDto
from .raw_client import AsyncRawMonitorsClient, RawMonitorsClient
from .types.disable_monitor_response import DisableMonitorResponse
from .types.enable_monitor_response import EnableMonitorResponse
@@ -44,6 +43,7 @@ def list_monitors(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ListMonitorsResponseDto:
"""
@@ -62,6 +62,9 @@ def list_monitors(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -77,10 +80,17 @@ def list_monitors(
client = CatchAllApi(
api_key="YOUR_API_KEY",
)
- client.monitors.list_monitors()
+ client.monitors.list_monitors(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
"""
_response = self._raw_client.list_monitors(
- page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ page=page,
+ page_size=page_size,
+ search=search,
+ ownership=ownership,
+ project_id=project_id,
+ request_options=request_options,
)
return _response.data
@@ -90,9 +100,10 @@ def create_monitor(
reference_job_id: str,
schedule: str,
timezone: typing.Optional[str] = OMIT,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
backfill: typing.Optional[bool] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> CreateMonitorResponseDto:
"""
@@ -113,8 +124,11 @@ def create_monitor(
If the schedule includes a timezone abbreviation (for example, `"every day at 9am EST"`), the parsed timezone takes priority and this value is ignored.
- webhook : typing.Optional[WebhookDto]
- Optional webhook to receive notifications when jobs complete.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of centralized webhooks to notify on each run completion.
+ Passing IDs here is equivalent to calling
+ `POST /catchAll/webhooks/{webhook_id}/resources` for each ID after creation.
+ Maximum 5 per monitor.
limit : typing.Optional[int]
Maximum number of records per monitor run. If not provided, defaults to the plan limit.
@@ -124,6 +138,9 @@ def create_monitor(
If false, no gap filling occurs and the first run uses the current cron window only — the reference job's age does not matter.
+ project_id : typing.Optional[str]
+ Project to assign this monitor to. The monitor appears in the project's resource list after creation.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -134,7 +151,7 @@ def create_monitor(
Examples
--------
- from newscatcher_catchall import CatchAllApi, WebhookDto
+ from newscatcher_catchall import CatchAllApi
client = CatchAllApi(
api_key="YOUR_API_KEY",
@@ -143,11 +160,7 @@ def create_monitor(
reference_job_id="5f0c9087-85cb-4917-b3c7-e5a5eff73a0c",
schedule="every day at 12 PM",
timezone="UTC",
- webhook=WebhookDto(
- url="https://your-endpoint.com/webhook",
- method="POST",
- headers={"Authorization": "Bearer your_token_here"},
- ),
+ webhook_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
limit=10,
backfill=True,
)
@@ -156,9 +169,10 @@ def create_monitor(
reference_job_id=reference_job_id,
schedule=schedule,
timezone=timezone,
- webhook=webhook,
+ webhook_ids=webhook_ids,
limit=limit,
backfill=backfill,
+ project_id=project_id,
request_options=request_options,
)
return _response.data
@@ -389,7 +403,7 @@ def update_monitor(
self,
monitor_id: str,
*,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> UpdateMonitorResponseDto:
@@ -401,8 +415,10 @@ def update_monitor(
monitor_id : str
Monitor identifier.
- webhook : typing.Optional[WebhookDto]
- Updated webhook configuration.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ Updated list of centralized webhook IDs for this monitor.
+
+ Replaces all existing webhook assignments. Pass an empty array `[]` to clear all assignments. Omit to leave existing assignments unchanged.
limit : typing.Optional[int]
Updated maximum number of records per monitor run.
@@ -417,22 +433,18 @@ def update_monitor(
Examples
--------
- from newscatcher_catchall import CatchAllApi, WebhookDto
+ from newscatcher_catchall import CatchAllApi
client = CatchAllApi(
api_key="YOUR_API_KEY",
)
client.monitors.update_monitor(
monitor_id="monitor_id",
- webhook=WebhookDto(
- url="https://new-endpoint.com/webhook",
- method="POST",
- headers={"Authorization": "Bearer new_token_xyz"},
- ),
+ webhook_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
)
"""
_response = self._raw_client.update_monitor(
- monitor_id, webhook=webhook, limit=limit, request_options=request_options
+ monitor_id, webhook_ids=webhook_ids, limit=limit, request_options=request_options
)
return _response.data
@@ -459,6 +471,7 @@ async def list_monitors(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ListMonitorsResponseDto:
"""
@@ -477,6 +490,9 @@ async def list_monitors(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -497,13 +513,20 @@ async def list_monitors(
async def main() -> None:
- await client.monitors.list_monitors()
+ await client.monitors.list_monitors(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
asyncio.run(main())
"""
_response = await self._raw_client.list_monitors(
- page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ page=page,
+ page_size=page_size,
+ search=search,
+ ownership=ownership,
+ project_id=project_id,
+ request_options=request_options,
)
return _response.data
@@ -513,9 +536,10 @@ async def create_monitor(
reference_job_id: str,
schedule: str,
timezone: typing.Optional[str] = OMIT,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
backfill: typing.Optional[bool] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> CreateMonitorResponseDto:
"""
@@ -536,8 +560,11 @@ async def create_monitor(
If the schedule includes a timezone abbreviation (for example, `"every day at 9am EST"`), the parsed timezone takes priority and this value is ignored.
- webhook : typing.Optional[WebhookDto]
- Optional webhook to receive notifications when jobs complete.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of centralized webhooks to notify on each run completion.
+ Passing IDs here is equivalent to calling
+ `POST /catchAll/webhooks/{webhook_id}/resources` for each ID after creation.
+ Maximum 5 per monitor.
limit : typing.Optional[int]
Maximum number of records per monitor run. If not provided, defaults to the plan limit.
@@ -547,6 +574,9 @@ async def create_monitor(
If false, no gap filling occurs and the first run uses the current cron window only — the reference job's age does not matter.
+ project_id : typing.Optional[str]
+ Project to assign this monitor to. The monitor appears in the project's resource list after creation.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -559,7 +589,7 @@ async def create_monitor(
--------
import asyncio
- from newscatcher_catchall import AsyncCatchAllApi, WebhookDto
+ from newscatcher_catchall import AsyncCatchAllApi
client = AsyncCatchAllApi(
api_key="YOUR_API_KEY",
@@ -571,11 +601,7 @@ async def main() -> None:
reference_job_id="5f0c9087-85cb-4917-b3c7-e5a5eff73a0c",
schedule="every day at 12 PM",
timezone="UTC",
- webhook=WebhookDto(
- url="https://your-endpoint.com/webhook",
- method="POST",
- headers={"Authorization": "Bearer your_token_here"},
- ),
+ webhook_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
limit=10,
backfill=True,
)
@@ -587,9 +613,10 @@ async def main() -> None:
reference_job_id=reference_job_id,
schedule=schedule,
timezone=timezone,
- webhook=webhook,
+ webhook_ids=webhook_ids,
limit=limit,
backfill=backfill,
+ project_id=project_id,
request_options=request_options,
)
return _response.data
@@ -870,7 +897,7 @@ async def update_monitor(
self,
monitor_id: str,
*,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> UpdateMonitorResponseDto:
@@ -882,8 +909,10 @@ async def update_monitor(
monitor_id : str
Monitor identifier.
- webhook : typing.Optional[WebhookDto]
- Updated webhook configuration.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ Updated list of centralized webhook IDs for this monitor.
+
+ Replaces all existing webhook assignments. Pass an empty array `[]` to clear all assignments. Omit to leave existing assignments unchanged.
limit : typing.Optional[int]
Updated maximum number of records per monitor run.
@@ -900,7 +929,7 @@ async def update_monitor(
--------
import asyncio
- from newscatcher_catchall import AsyncCatchAllApi, WebhookDto
+ from newscatcher_catchall import AsyncCatchAllApi
client = AsyncCatchAllApi(
api_key="YOUR_API_KEY",
@@ -910,17 +939,13 @@ async def update_monitor(
async def main() -> None:
await client.monitors.update_monitor(
monitor_id="monitor_id",
- webhook=WebhookDto(
- url="https://new-endpoint.com/webhook",
- method="POST",
- headers={"Authorization": "Bearer new_token_xyz"},
- ),
+ webhook_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
)
asyncio.run(main())
"""
_response = await self._raw_client.update_monitor(
- monitor_id, webhook=webhook, limit=limit, request_options=request_options
+ monitor_id, webhook_ids=webhook_ids, limit=limit, request_options=request_options
)
return _response.data
diff --git a/src/newscatcher_catchall/monitors/raw_client.py b/src/newscatcher_catchall/monitors/raw_client.py
index f1db5d0..16f87f1 100644
--- a/src/newscatcher_catchall/monitors/raw_client.py
+++ b/src/newscatcher_catchall/monitors/raw_client.py
@@ -10,7 +10,6 @@
from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
-from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.forbidden_error import ForbiddenError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
@@ -24,7 +23,6 @@
from ..types.pull_monitor_response_dto import PullMonitorResponseDto
from ..types.update_monitor_response_dto import UpdateMonitorResponseDto
from ..types.validation_error_response import ValidationErrorResponse
-from ..types.webhook_dto import WebhookDto
from .types.disable_monitor_response import DisableMonitorResponse
from .types.enable_monitor_response import EnableMonitorResponse
from .types.list_monitor_jobs_request_sort import ListMonitorJobsRequestSort
@@ -46,6 +44,7 @@ def list_monitors(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[ListMonitorsResponseDto]:
"""
@@ -64,6 +63,9 @@ def list_monitors(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -80,6 +82,7 @@ def list_monitors(
"page_size": page_size,
"search": search,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
@@ -130,9 +133,10 @@ def create_monitor(
reference_job_id: str,
schedule: str,
timezone: typing.Optional[str] = OMIT,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
backfill: typing.Optional[bool] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[CreateMonitorResponseDto]:
"""
@@ -153,8 +157,11 @@ def create_monitor(
If the schedule includes a timezone abbreviation (for example, `"every day at 9am EST"`), the parsed timezone takes priority and this value is ignored.
- webhook : typing.Optional[WebhookDto]
- Optional webhook to receive notifications when jobs complete.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of centralized webhooks to notify on each run completion.
+ Passing IDs here is equivalent to calling
+ `POST /catchAll/webhooks/{webhook_id}/resources` for each ID after creation.
+ Maximum 5 per monitor.
limit : typing.Optional[int]
Maximum number of records per monitor run. If not provided, defaults to the plan limit.
@@ -164,6 +171,9 @@ def create_monitor(
If false, no gap filling occurs and the first run uses the current cron window only — the reference job's age does not matter.
+ project_id : typing.Optional[str]
+ Project to assign this monitor to. The monitor appears in the project's resource list after creation.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -179,11 +189,10 @@ def create_monitor(
"reference_job_id": reference_job_id,
"schedule": schedule,
"timezone": timezone,
- "webhook": convert_and_respect_annotation_metadata(
- object_=webhook, annotation=WebhookDto, direction="write"
- ),
+ "webhook_ids": webhook_ids,
"limit": limit,
"backfill": backfill,
+ "project_id": project_id,
},
headers={
"content-type": "application/json",
@@ -670,7 +679,7 @@ def update_monitor(
self,
monitor_id: str,
*,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[UpdateMonitorResponseDto]:
@@ -682,8 +691,10 @@ def update_monitor(
monitor_id : str
Monitor identifier.
- webhook : typing.Optional[WebhookDto]
- Updated webhook configuration.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ Updated list of centralized webhook IDs for this monitor.
+
+ Replaces all existing webhook assignments. Pass an empty array `[]` to clear all assignments. Omit to leave existing assignments unchanged.
limit : typing.Optional[int]
Updated maximum number of records per monitor run.
@@ -700,9 +711,7 @@ def update_monitor(
f"catchAll/monitors/{encode_path_param(monitor_id)}",
method="PATCH",
json={
- "webhook": convert_and_respect_annotation_metadata(
- object_=webhook, annotation=WebhookDto, direction="write"
- ),
+ "webhook_ids": webhook_ids,
"limit": limit,
},
headers={
@@ -775,6 +784,7 @@ async def list_monitors(
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
ownership: typing.Optional[OwnershipFilter] = None,
+ project_id: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[ListMonitorsResponseDto]:
"""
@@ -793,6 +803,9 @@ async def list_monitors(
ownership : typing.Optional[OwnershipFilter]
+ project_id : typing.Optional[str]
+ Filter results to resources belonging to this project.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -809,6 +822,7 @@ async def list_monitors(
"page_size": page_size,
"search": search,
"ownership": ownership,
+ "project_id": project_id,
},
request_options=request_options,
)
@@ -859,9 +873,10 @@ async def create_monitor(
reference_job_id: str,
schedule: str,
timezone: typing.Optional[str] = OMIT,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
backfill: typing.Optional[bool] = OMIT,
+ project_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[CreateMonitorResponseDto]:
"""
@@ -882,8 +897,11 @@ async def create_monitor(
If the schedule includes a timezone abbreviation (for example, `"every day at 9am EST"`), the parsed timezone takes priority and this value is ignored.
- webhook : typing.Optional[WebhookDto]
- Optional webhook to receive notifications when jobs complete.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ IDs of centralized webhooks to notify on each run completion.
+ Passing IDs here is equivalent to calling
+ `POST /catchAll/webhooks/{webhook_id}/resources` for each ID after creation.
+ Maximum 5 per monitor.
limit : typing.Optional[int]
Maximum number of records per monitor run. If not provided, defaults to the plan limit.
@@ -893,6 +911,9 @@ async def create_monitor(
If false, no gap filling occurs and the first run uses the current cron window only — the reference job's age does not matter.
+ project_id : typing.Optional[str]
+ Project to assign this monitor to. The monitor appears in the project's resource list after creation.
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -908,11 +929,10 @@ async def create_monitor(
"reference_job_id": reference_job_id,
"schedule": schedule,
"timezone": timezone,
- "webhook": convert_and_respect_annotation_metadata(
- object_=webhook, annotation=WebhookDto, direction="write"
- ),
+ "webhook_ids": webhook_ids,
"limit": limit,
"backfill": backfill,
+ "project_id": project_id,
},
headers={
"content-type": "application/json",
@@ -1399,7 +1419,7 @@ async def update_monitor(
self,
monitor_id: str,
*,
- webhook: typing.Optional[WebhookDto] = OMIT,
+ webhook_ids: typing.Optional[typing.Sequence[str]] = OMIT,
limit: typing.Optional[int] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[UpdateMonitorResponseDto]:
@@ -1411,8 +1431,10 @@ async def update_monitor(
monitor_id : str
Monitor identifier.
- webhook : typing.Optional[WebhookDto]
- Updated webhook configuration.
+ webhook_ids : typing.Optional[typing.Sequence[str]]
+ Updated list of centralized webhook IDs for this monitor.
+
+ Replaces all existing webhook assignments. Pass an empty array `[]` to clear all assignments. Omit to leave existing assignments unchanged.
limit : typing.Optional[int]
Updated maximum number of records per monitor run.
@@ -1429,9 +1451,7 @@ async def update_monitor(
f"catchAll/monitors/{encode_path_param(monitor_id)}",
method="PATCH",
json={
- "webhook": convert_and_respect_annotation_metadata(
- object_=webhook, annotation=WebhookDto, direction="write"
- ),
+ "webhook_ids": webhook_ids,
"limit": limit,
},
headers={
diff --git a/src/newscatcher_catchall/monitors/types/disable_monitor_response.py b/src/newscatcher_catchall/monitors/types/disable_monitor_response.py
index f68ea08..b9769cf 100644
--- a/src/newscatcher_catchall/monitors/types/disable_monitor_response.py
+++ b/src/newscatcher_catchall/monitors/types/disable_monitor_response.py
@@ -9,7 +9,7 @@
class DisableMonitorResponse(UniversalBaseModel):
success: bool = pydantic.Field()
"""
- Whether the operation succeeded.
+ True if the operation succeeded; false otherwise.
"""
message: str = pydantic.Field()
diff --git a/src/newscatcher_catchall/monitors/types/enable_monitor_response.py b/src/newscatcher_catchall/monitors/types/enable_monitor_response.py
index b5d8a69..d87d0d1 100644
--- a/src/newscatcher_catchall/monitors/types/enable_monitor_response.py
+++ b/src/newscatcher_catchall/monitors/types/enable_monitor_response.py
@@ -9,7 +9,7 @@
class EnableMonitorResponse(UniversalBaseModel):
success: bool = pydantic.Field()
"""
- Whether the operation succeeded.
+ True if the operation succeeded; false otherwise.
"""
message: str = pydantic.Field()
diff --git a/src/newscatcher_catchall/projects/__init__.py b/src/newscatcher_catchall/projects/__init__.py
new file mode 100644
index 0000000..5cde020
--- /dev/null
+++ b/src/newscatcher_catchall/projects/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/newscatcher_catchall/projects/client.py b/src/newscatcher_catchall/projects/client.py
new file mode 100644
index 0000000..1fc9cfd
--- /dev/null
+++ b/src/newscatcher_catchall/projects/client.py
@@ -0,0 +1,909 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.request_options import RequestOptions
+from ..types.add_resource_response_dto import AddResourceResponseDto
+from ..types.create_project_response_dto import CreateProjectResponseDto
+from ..types.ownership_filter import OwnershipFilter
+from ..types.project_list_response_dto import ProjectListResponseDto
+from ..types.project_overview_response_dto import ProjectOverviewResponseDto
+from ..types.project_resource_list_response_dto import ProjectResourceListResponseDto
+from ..types.project_resource_type import ProjectResourceType
+from ..types.project_response_dto import ProjectResponseDto
+from ..types.remove_resource_response_dto import RemoveResourceResponseDto
+from ..types.resource_item_dto import ResourceItemDto
+from ..types.update_project_response_dto import UpdateProjectResponseDto
+from .raw_client import AsyncRawProjectsClient, RawProjectsClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class ProjectsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawProjectsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawProjectsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawProjectsClient
+ """
+ return self._raw_client
+
+ def list_projects(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ ownership: typing.Optional[OwnershipFilter] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ProjectListResponseDto:
+ """
+ Returns all projects visible to the authenticated user.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ search : typing.Optional[str]
+ Filter by project name (case-insensitive substring match).
+
+ ownership : typing.Optional[OwnershipFilter]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectListResponseDto
+ Paginated list of projects.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.list_projects(
+ search="M&A",
+ )
+ """
+ _response = self._raw_client.list_projects(
+ page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ )
+ return _response.data
+
+ def create_project(
+ self,
+ *,
+ name: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CreateProjectResponseDto:
+ """
+ Creates a new project.
+
+ Parameters
+ ----------
+ name : str
+ Name for the project.
+
+ description : typing.Optional[str]
+ Optional description.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CreateProjectResponseDto
+ Project created successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.create_project(
+ name="AI M&A Tracking",
+ description="Tracks AI-related M&A activity for our investment team.",
+ )
+ """
+ _response = self._raw_client.create_project(name=name, description=description, request_options=request_options)
+ return _response.data
+
+ def get_project(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ProjectResponseDto:
+ """
+ Returns a single project by ID.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectResponseDto
+ Project details.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.get_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+ """
+ _response = self._raw_client.get_project(project_id, request_options=request_options)
+ return _response.data
+
+ def delete_project(
+ self,
+ project_id: str,
+ *,
+ delete_resources: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> None:
+ """
+ Deletes a project. By default, assigned resources are unassigned but not deleted.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ delete_resources : typing.Optional[bool]
+ If true, permanently deletes all resources (jobs, monitors, datasets) assigned to the project. If false, the project is deleted and its resources are unassigned but not deleted.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.delete_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+ """
+ _response = self._raw_client.delete_project(
+ project_id, delete_resources=delete_resources, request_options=request_options
+ )
+ return _response.data
+
+ def update_project(
+ self,
+ project_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> UpdateProjectResponseDto:
+ """
+ Updates the name or description of an existing project.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ name : typing.Optional[str]
+ New name for the project.
+
+ description : typing.Optional[str]
+ New description for the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UpdateProjectResponseDto
+ Project updated successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.update_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ name="AI M&A Tracking (Q2 2026)",
+ )
+ """
+ _response = self._raw_client.update_project(
+ project_id, name=name, description=description, request_options=request_options
+ )
+ return _response.data
+
+ def get_project_overview(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ProjectOverviewResponseDto:
+ """
+ Returns resource counts for a project, grouped by type and status.
+
+ For `jobs` and `monitors`, counts are broken down by status (for example, `completed`, `failed`). For `datasets` and `monitor_groups`, only a `total` count is returned.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectOverviewResponseDto
+ Resource counts for the project, grouped by type and status.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.get_project_overview(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+ """
+ _response = self._raw_client.get_project_overview(project_id, request_options=request_options)
+ return _response.data
+
+ def list_project_resources(
+ self,
+ project_id: str,
+ *,
+ resource_type: typing.Optional[ProjectResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ProjectResourceListResponseDto:
+ """
+ Returns all resources assigned to a project, with optional filtering by type.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : typing.Optional[ProjectResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectResourceListResponseDto
+ Paginated list of resources assigned to the project.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.list_project_resources(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+ """
+ _response = self._raw_client.list_project_resources(
+ project_id, resource_type=resource_type, page=page, page_size=page_size, request_options=request_options
+ )
+ return _response.data
+
+ def add_resource_to_project(
+ self,
+ project_id: str,
+ *,
+ resources: typing.Sequence[ResourceItemDto],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AddResourceResponseDto:
+ """
+ Assigns one or more existing resources to a project in a single request.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resources : typing.Sequence[ResourceItemDto]
+ Resources to assign to the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AddResourceResponseDto
+ One or more resources added to the project (`201`), or all were already present (`200`).
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi, ResourceItemDto
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.add_resource_to_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resources=[
+ ResourceItemDto(
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
+ )
+ ],
+ )
+ """
+ _response = self._raw_client.add_resource_to_project(
+ project_id, resources=resources, request_options=request_options
+ )
+ return _response.data
+
+ def remove_resource_from_project(
+ self,
+ project_id: str,
+ resource_type: ProjectResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> RemoveResourceResponseDto:
+ """
+ Removes a resource from a project. The resource itself is not
+ deleted — it becomes unassigned and continues to exist.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : ProjectResourceType
+
+ resource_id : str
+ ID of the resource to remove.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoveResourceResponseDto
+ Resource removed from the project.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.projects.remove_resource_from_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
+ )
+ """
+ _response = self._raw_client.remove_resource_from_project(
+ project_id, resource_type, resource_id, request_options=request_options
+ )
+ return _response.data
+
+
+class AsyncProjectsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawProjectsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawProjectsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawProjectsClient
+ """
+ return self._raw_client
+
+ async def list_projects(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ ownership: typing.Optional[OwnershipFilter] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ProjectListResponseDto:
+ """
+ Returns all projects visible to the authenticated user.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ search : typing.Optional[str]
+ Filter by project name (case-insensitive substring match).
+
+ ownership : typing.Optional[OwnershipFilter]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectListResponseDto
+ Paginated list of projects.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.list_projects(
+ search="M&A",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list_projects(
+ page=page, page_size=page_size, search=search, ownership=ownership, request_options=request_options
+ )
+ return _response.data
+
+ async def create_project(
+ self,
+ *,
+ name: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CreateProjectResponseDto:
+ """
+ Creates a new project.
+
+ Parameters
+ ----------
+ name : str
+ Name for the project.
+
+ description : typing.Optional[str]
+ Optional description.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CreateProjectResponseDto
+ Project created successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.create_project(
+ name="AI M&A Tracking",
+ description="Tracks AI-related M&A activity for our investment team.",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create_project(
+ name=name, description=description, request_options=request_options
+ )
+ return _response.data
+
+ async def get_project(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ProjectResponseDto:
+ """
+ Returns a single project by ID.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectResponseDto
+ Project details.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.get_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_project(project_id, request_options=request_options)
+ return _response.data
+
+ async def delete_project(
+ self,
+ project_id: str,
+ *,
+ delete_resources: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> None:
+ """
+ Deletes a project. By default, assigned resources are unassigned but not deleted.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ delete_resources : typing.Optional[bool]
+ If true, permanently deletes all resources (jobs, monitors, datasets) assigned to the project. If false, the project is deleted and its resources are unassigned but not deleted.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.delete_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.delete_project(
+ project_id, delete_resources=delete_resources, request_options=request_options
+ )
+ return _response.data
+
+ async def update_project(
+ self,
+ project_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> UpdateProjectResponseDto:
+ """
+ Updates the name or description of an existing project.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ name : typing.Optional[str]
+ New name for the project.
+
+ description : typing.Optional[str]
+ New description for the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UpdateProjectResponseDto
+ Project updated successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.update_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ name="AI M&A Tracking (Q2 2026)",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.update_project(
+ project_id, name=name, description=description, request_options=request_options
+ )
+ return _response.data
+
+ async def get_project_overview(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ProjectOverviewResponseDto:
+ """
+ Returns resource counts for a project, grouped by type and status.
+
+ For `jobs` and `monitors`, counts are broken down by status (for example, `completed`, `failed`). For `datasets` and `monitor_groups`, only a `total` count is returned.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectOverviewResponseDto
+ Resource counts for the project, grouped by type and status.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.get_project_overview(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_project_overview(project_id, request_options=request_options)
+ return _response.data
+
+ async def list_project_resources(
+ self,
+ project_id: str,
+ *,
+ resource_type: typing.Optional[ProjectResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ProjectResourceListResponseDto:
+ """
+ Returns all resources assigned to a project, with optional filtering by type.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : typing.Optional[ProjectResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ProjectResourceListResponseDto
+ Paginated list of resources assigned to the project.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.list_project_resources(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list_project_resources(
+ project_id, resource_type=resource_type, page=page, page_size=page_size, request_options=request_options
+ )
+ return _response.data
+
+ async def add_resource_to_project(
+ self,
+ project_id: str,
+ *,
+ resources: typing.Sequence[ResourceItemDto],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AddResourceResponseDto:
+ """
+ Assigns one or more existing resources to a project in a single request.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resources : typing.Sequence[ResourceItemDto]
+ Resources to assign to the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AddResourceResponseDto
+ One or more resources added to the project (`201`), or all were already present (`200`).
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi, ResourceItemDto
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.add_resource_to_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resources=[
+ ResourceItemDto(
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
+ )
+ ],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.add_resource_to_project(
+ project_id, resources=resources, request_options=request_options
+ )
+ return _response.data
+
+ async def remove_resource_from_project(
+ self,
+ project_id: str,
+ resource_type: ProjectResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> RemoveResourceResponseDto:
+ """
+ Removes a resource from a project. The resource itself is not
+ deleted — it becomes unassigned and continues to exist.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : ProjectResourceType
+
+ resource_id : str
+ ID of the resource to remove.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoveResourceResponseDto
+ Resource removed from the project.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.projects.remove_resource_from_project(
+ project_id="60a85db4-78ec-4b78-876a-bc7d9cdadd04",
+ resource_type="job",
+ resource_id="48421e16-1f50-4048-b62c-d3bc0789d30d",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.remove_resource_from_project(
+ project_id, resource_type, resource_id, request_options=request_options
+ )
+ return _response.data
diff --git a/src/newscatcher_catchall/projects/raw_client.py b/src/newscatcher_catchall/projects/raw_client.py
new file mode 100644
index 0000000..69d9d31
--- /dev/null
+++ b/src/newscatcher_catchall/projects/raw_client.py
@@ -0,0 +1,1488 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from ..core.api_error import ApiError
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
+from ..core.pydantic_utilities import parse_obj_as
+from ..core.request_options import RequestOptions
+from ..core.serialization import convert_and_respect_annotation_metadata
+from ..errors.bad_request_error import BadRequestError
+from ..errors.forbidden_error import ForbiddenError
+from ..errors.not_found_error import NotFoundError
+from ..errors.unprocessable_entity_error import UnprocessableEntityError
+from ..types.add_resource_response_dto import AddResourceResponseDto
+from ..types.create_project_response_dto import CreateProjectResponseDto
+from ..types.error import Error
+from ..types.ownership_filter import OwnershipFilter
+from ..types.project_list_response_dto import ProjectListResponseDto
+from ..types.project_overview_response_dto import ProjectOverviewResponseDto
+from ..types.project_resource_list_response_dto import ProjectResourceListResponseDto
+from ..types.project_resource_type import ProjectResourceType
+from ..types.project_response_dto import ProjectResponseDto
+from ..types.remove_resource_response_dto import RemoveResourceResponseDto
+from ..types.resource_item_dto import ResourceItemDto
+from ..types.update_project_response_dto import UpdateProjectResponseDto
+from ..types.validation_error_response import ValidationErrorResponse
+from pydantic import ValidationError
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawProjectsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list_projects(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ ownership: typing.Optional[OwnershipFilter] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ProjectListResponseDto]:
+ """
+ Returns all projects visible to the authenticated user.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ search : typing.Optional[str]
+ Filter by project name (case-insensitive substring match).
+
+ ownership : typing.Optional[OwnershipFilter]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ProjectListResponseDto]
+ Paginated list of projects.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/projects",
+ method="GET",
+ params={
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "ownership": ownership,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectListResponseDto,
+ parse_obj_as(
+ type_=ProjectListResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def create_project(
+ self,
+ *,
+ name: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[CreateProjectResponseDto]:
+ """
+ Creates a new project.
+
+ Parameters
+ ----------
+ name : str
+ Name for the project.
+
+ description : typing.Optional[str]
+ Optional description.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[CreateProjectResponseDto]
+ Project created successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/projects",
+ method="POST",
+ json={
+ "name": name,
+ "description": description,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CreateProjectResponseDto,
+ parse_obj_as(
+ type_=CreateProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def get_project(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[ProjectResponseDto]:
+ """
+ Returns a single project by ID.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ProjectResponseDto]
+ Project details.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectResponseDto,
+ parse_obj_as(
+ type_=ProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def delete_project(
+ self,
+ project_id: str,
+ *,
+ delete_resources: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[None]:
+ """
+ Deletes a project. By default, assigned resources are unassigned but not deleted.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ delete_resources : typing.Optional[bool]
+ If true, permanently deletes all resources (jobs, monitors, datasets) assigned to the project. If false, the project is deleted and its resources are unassigned but not deleted.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="DELETE",
+ params={
+ "delete_resources": delete_resources,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def update_project(
+ self,
+ project_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[UpdateProjectResponseDto]:
+ """
+ Updates the name or description of an existing project.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ name : typing.Optional[str]
+ New name for the project.
+
+ description : typing.Optional[str]
+ New description for the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[UpdateProjectResponseDto]
+ Project updated successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="PATCH",
+ json={
+ "name": name,
+ "description": description,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UpdateProjectResponseDto,
+ parse_obj_as(
+ type_=UpdateProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def get_project_overview(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[ProjectOverviewResponseDto]:
+ """
+ Returns resource counts for a project, grouped by type and status.
+
+ For `jobs` and `monitors`, counts are broken down by status (for example, `completed`, `failed`). For `datasets` and `monitor_groups`, only a `total` count is returned.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ProjectOverviewResponseDto]
+ Resource counts for the project, grouped by type and status.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/overview",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectOverviewResponseDto,
+ parse_obj_as(
+ type_=ProjectOverviewResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def list_project_resources(
+ self,
+ project_id: str,
+ *,
+ resource_type: typing.Optional[ProjectResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ProjectResourceListResponseDto]:
+ """
+ Returns all resources assigned to a project, with optional filtering by type.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : typing.Optional[ProjectResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ProjectResourceListResponseDto]
+ Paginated list of resources assigned to the project.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectResourceListResponseDto,
+ parse_obj_as(
+ type_=ProjectResourceListResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def add_resource_to_project(
+ self,
+ project_id: str,
+ *,
+ resources: typing.Sequence[ResourceItemDto],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[AddResourceResponseDto]:
+ """
+ Assigns one or more existing resources to a project in a single request.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resources : typing.Sequence[ResourceItemDto]
+ Resources to assign to the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AddResourceResponseDto]
+ One or more resources added to the project (`201`), or all were already present (`200`).
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources",
+ method="POST",
+ json={
+ "resources": convert_and_respect_annotation_metadata(
+ object_=resources, annotation=typing.Sequence[ResourceItemDto], direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AddResourceResponseDto,
+ parse_obj_as(
+ type_=AddResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Any,
+ parse_obj_as(
+ type_=typing.Any, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def remove_resource_from_project(
+ self,
+ project_id: str,
+ resource_type: ProjectResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[RemoveResourceResponseDto]:
+ """
+ Removes a resource from a project. The resource itself is not
+ deleted — it becomes unassigned and continues to exist.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : ProjectResourceType
+
+ resource_id : str
+ ID of the resource to remove.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RemoveResourceResponseDto]
+ Resource removed from the project.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoveResourceResponseDto,
+ parse_obj_as(
+ type_=RemoveResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawProjectsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list_projects(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ ownership: typing.Optional[OwnershipFilter] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ProjectListResponseDto]:
+ """
+ Returns all projects visible to the authenticated user.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ search : typing.Optional[str]
+ Filter by project name (case-insensitive substring match).
+
+ ownership : typing.Optional[OwnershipFilter]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ProjectListResponseDto]
+ Paginated list of projects.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/projects",
+ method="GET",
+ params={
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "ownership": ownership,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectListResponseDto,
+ parse_obj_as(
+ type_=ProjectListResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def create_project(
+ self,
+ *,
+ name: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[CreateProjectResponseDto]:
+ """
+ Creates a new project.
+
+ Parameters
+ ----------
+ name : str
+ Name for the project.
+
+ description : typing.Optional[str]
+ Optional description.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[CreateProjectResponseDto]
+ Project created successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/projects",
+ method="POST",
+ json={
+ "name": name,
+ "description": description,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CreateProjectResponseDto,
+ parse_obj_as(
+ type_=CreateProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def get_project(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[ProjectResponseDto]:
+ """
+ Returns a single project by ID.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ProjectResponseDto]
+ Project details.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectResponseDto,
+ parse_obj_as(
+ type_=ProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def delete_project(
+ self,
+ project_id: str,
+ *,
+ delete_resources: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[None]:
+ """
+ Deletes a project. By default, assigned resources are unassigned but not deleted.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ delete_resources : typing.Optional[bool]
+ If true, permanently deletes all resources (jobs, monitors, datasets) assigned to the project. If false, the project is deleted and its resources are unassigned but not deleted.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="DELETE",
+ params={
+ "delete_resources": delete_resources,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def update_project(
+ self,
+ project_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[UpdateProjectResponseDto]:
+ """
+ Updates the name or description of an existing project.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ name : typing.Optional[str]
+ New name for the project.
+
+ description : typing.Optional[str]
+ New description for the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[UpdateProjectResponseDto]
+ Project updated successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}",
+ method="PATCH",
+ json={
+ "name": name,
+ "description": description,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UpdateProjectResponseDto,
+ parse_obj_as(
+ type_=UpdateProjectResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def get_project_overview(
+ self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[ProjectOverviewResponseDto]:
+ """
+ Returns resource counts for a project, grouped by type and status.
+
+ For `jobs` and `monitors`, counts are broken down by status (for example, `completed`, `failed`). For `datasets` and `monitor_groups`, only a `total` count is returned.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ProjectOverviewResponseDto]
+ Resource counts for the project, grouped by type and status.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/overview",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectOverviewResponseDto,
+ parse_obj_as(
+ type_=ProjectOverviewResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def list_project_resources(
+ self,
+ project_id: str,
+ *,
+ resource_type: typing.Optional[ProjectResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ProjectResourceListResponseDto]:
+ """
+ Returns all resources assigned to a project, with optional filtering by type.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : typing.Optional[ProjectResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ProjectResourceListResponseDto]
+ Paginated list of resources assigned to the project.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ProjectResourceListResponseDto,
+ parse_obj_as(
+ type_=ProjectResourceListResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def add_resource_to_project(
+ self,
+ project_id: str,
+ *,
+ resources: typing.Sequence[ResourceItemDto],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[AddResourceResponseDto]:
+ """
+ Assigns one or more existing resources to a project in a single request.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resources : typing.Sequence[ResourceItemDto]
+ Resources to assign to the project.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AddResourceResponseDto]
+ One or more resources added to the project (`201`), or all were already present (`200`).
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources",
+ method="POST",
+ json={
+ "resources": convert_and_respect_annotation_metadata(
+ object_=resources, annotation=typing.Sequence[ResourceItemDto], direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AddResourceResponseDto,
+ parse_obj_as(
+ type_=AddResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Any,
+ parse_obj_as(
+ type_=typing.Any, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def remove_resource_from_project(
+ self,
+ project_id: str,
+ resource_type: ProjectResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[RemoveResourceResponseDto]:
+ """
+ Removes a resource from a project. The resource itself is not
+ deleted — it becomes unassigned and continues to exist.
+
+ Parameters
+ ----------
+ project_id : str
+ Unique project identifier.
+
+ resource_type : ProjectResourceType
+
+ resource_id : str
+ ID of the resource to remove.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RemoveResourceResponseDto]
+ Resource removed from the project.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/projects/{encode_path_param(project_id)}/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoveResourceResponseDto,
+ parse_obj_as(
+ type_=RemoveResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/newscatcher_catchall/types/__init__.py b/src/newscatcher_catchall/types/__init__.py
index 61316a2..53f61a1 100644
--- a/src/newscatcher_catchall/types/__init__.py
+++ b/src/newscatcher_catchall/types/__init__.py
@@ -6,10 +6,15 @@
from importlib import import_module
if typing.TYPE_CHECKING:
+ from .add_resource_response_dto import AddResourceResponseDto
from .additional_attributes import AdditionalAttributes
+ from .api_key_auth_dto import ApiKeyAuthDto
+ from .assign_webhook_resource_response_dto import AssignWebhookResourceResponseDto
from .base_record import BaseRecord
from .base_record_enrichment import BaseRecordEnrichment
from .base_record_enrichment_enrichment_confidence import BaseRecordEnrichmentEnrichmentConfidence
+ from .basic_auth_dto import BasicAuthDto
+ from .bearer_auth_dto import BearerAuthDto
from .citation import Citation
from .company_attributes import CompanyAttributes
from .company_enrichment_output import CompanyEnrichmentOutput
@@ -25,6 +30,8 @@
from .create_entity_request import CreateEntityRequest
from .create_entity_response import CreateEntityResponse
from .create_monitor_response_dto import CreateMonitorResponseDto
+ from .create_project_response_dto import CreateProjectResponseDto
+ from .create_webhook_response_dto import CreateWebhookResponseDto
from .dataset_entity_ids_request import DatasetEntityIdsRequest
from .dataset_entity_list_response import DatasetEntityListResponse
from .dataset_list_response import DatasetListResponse
@@ -35,6 +42,10 @@
from .dataset_status_history_response import DatasetStatusHistoryResponse
from .delete_job_response_dto import DeleteJobResponseDto
from .delete_monitor_response_dto import DeleteMonitorResponseDto
+ from .delivery_history_item_dto import DeliveryHistoryItemDto
+ from .delivery_history_response_dto import DeliveryHistoryResponseDto
+ from .delivery_mode import DeliveryMode
+ from .delivery_status import DeliveryStatus
from .end_date import EndDate
from .enrichment_schema import EnrichmentSchema
from .enrichment_type import EnrichmentType
@@ -47,12 +58,18 @@
from .entity_validation_error_body import EntityValidationErrorBody
from .error import Error
from .get_plan_limits_response_dto import GetPlanLimitsResponseDto
+ from .get_webhook_response_dto import GetWebhookResponseDto
+ from .http_method import HttpMethod
from .initialize_response_dto import InitializeResponseDto
+ from .issue_type import IssueType
from .job_step import JobStep
from .limit import Limit
from .list_monitors_response_dto import ListMonitorsResponseDto
from .list_user_jobs_response_dto import ListUserJobsResponseDto
+ from .list_webhook_resources_response_dto import ListWebhookResourcesResponseDto
+ from .list_webhooks_response_dto import ListWebhooksResponseDto
from .manage_entities_response import ManageEntitiesResponse
+ from .mappable_resource_type import MappableResourceType
from .monitor_citation import MonitorCitation
from .monitor_job_item import MonitorJobItem
from .monitor_list_item_dto import MonitorListItemDto
@@ -62,6 +79,15 @@
from .monitor_status_history_response_dto import MonitorStatusHistoryResponseDto
from .ownership_filter import OwnershipFilter
from .plan_feature import PlanFeature
+ from .project_list_response_dto import ProjectListResponseDto
+ from .project_overview_counts_dto import ProjectOverviewCountsDto
+ from .project_overview_response_dto import ProjectOverviewResponseDto
+ from .project_overview_response_dto_overview import ProjectOverviewResponseDtoOverview
+ from .project_resource_dto import ProjectResourceDto
+ from .project_resource_list_response_dto import ProjectResourceListResponseDto
+ from .project_resource_type import ProjectResourceType
+ from .project_response_dto import ProjectResponseDto
+ from .project_summary_dto import ProjectSummaryDto
from .public_job_status import PublicJobStatus
from .pull_job_response_dto import PullJobResponseDto
from .pull_job_response_dto_date_range import PullJobResponseDtoDateRange
@@ -69,8 +95,12 @@
from .pull_monitor_response_dto import PullMonitorResponseDto
from .pull_monitor_response_dto_run_info import PullMonitorResponseDtoRunInfo
from .query import Query
+ from .query_status import QueryStatus
from .record import Record
from .reference_job import ReferenceJob
+ from .remove_resource_response_dto import RemoveResourceResponseDto
+ from .resource_item_dto import ResourceItemDto
+ from .resource_result_dto import ResourceResultDto
from .sharing_info import SharingInfo
from .sharing_info_permission import SharingInfoPermission
from .skipped_row import SkippedRow
@@ -78,10 +108,15 @@
from .start_date import StartDate
from .status_response_dto import StatusResponseDto
from .submit_response_dto import SubmitResponseDto
+ from .suggestion import Suggestion
+ from .test_webhook_response_dto import TestWebhookResponseDto
from .update_monitor_response_dto import UpdateMonitorResponseDto
+ from .update_project_response_dto import UpdateProjectResponseDto
+ from .update_webhook_response_dto import UpdateWebhookResponseDto
from .upload_csv_to_dataset_response import UploadCsvToDatasetResponse
from .user_job import UserJob
from .user_job_mode import UserJobMode
+ from .validate_query_response_dto import ValidateQueryResponseDto
from .validation_error_detail import ValidationErrorDetail
from .validation_error_detail_loc_item import ValidationErrorDetailLocItem
from .validation_error_response import ValidationErrorResponse
@@ -90,11 +125,19 @@
from .webhook_dto import WebhookDto
from .webhook_dto_method import WebhookDtoMethod
from .webhook_payload import WebhookPayload
+ from .webhook_resource_mapping_response_dto import WebhookResourceMappingResponseDto
+ from .webhook_response_dto import WebhookResponseDto
+ from .webhook_type import WebhookType
_dynamic_imports: typing.Dict[str, str] = {
+ "AddResourceResponseDto": ".add_resource_response_dto",
"AdditionalAttributes": ".additional_attributes",
+ "ApiKeyAuthDto": ".api_key_auth_dto",
+ "AssignWebhookResourceResponseDto": ".assign_webhook_resource_response_dto",
"BaseRecord": ".base_record",
"BaseRecordEnrichment": ".base_record_enrichment",
"BaseRecordEnrichmentEnrichmentConfidence": ".base_record_enrichment_enrichment_confidence",
+ "BasicAuthDto": ".basic_auth_dto",
+ "BearerAuthDto": ".bearer_auth_dto",
"Citation": ".citation",
"CompanyAttributes": ".company_attributes",
"CompanyEnrichmentOutput": ".company_enrichment_output",
@@ -108,6 +151,8 @@
"CreateEntityRequest": ".create_entity_request",
"CreateEntityResponse": ".create_entity_response",
"CreateMonitorResponseDto": ".create_monitor_response_dto",
+ "CreateProjectResponseDto": ".create_project_response_dto",
+ "CreateWebhookResponseDto": ".create_webhook_response_dto",
"DatasetEntityIdsRequest": ".dataset_entity_ids_request",
"DatasetEntityListResponse": ".dataset_entity_list_response",
"DatasetListResponse": ".dataset_list_response",
@@ -118,6 +163,10 @@
"DatasetStatusHistoryResponse": ".dataset_status_history_response",
"DeleteJobResponseDto": ".delete_job_response_dto",
"DeleteMonitorResponseDto": ".delete_monitor_response_dto",
+ "DeliveryHistoryItemDto": ".delivery_history_item_dto",
+ "DeliveryHistoryResponseDto": ".delivery_history_response_dto",
+ "DeliveryMode": ".delivery_mode",
+ "DeliveryStatus": ".delivery_status",
"EndDate": ".end_date",
"EnrichmentSchema": ".enrichment_schema",
"EnrichmentType": ".enrichment_type",
@@ -130,12 +179,18 @@
"EntityValidationErrorBody": ".entity_validation_error_body",
"Error": ".error",
"GetPlanLimitsResponseDto": ".get_plan_limits_response_dto",
+ "GetWebhookResponseDto": ".get_webhook_response_dto",
+ "HttpMethod": ".http_method",
"InitializeResponseDto": ".initialize_response_dto",
+ "IssueType": ".issue_type",
"JobStep": ".job_step",
"Limit": ".limit",
"ListMonitorsResponseDto": ".list_monitors_response_dto",
"ListUserJobsResponseDto": ".list_user_jobs_response_dto",
+ "ListWebhookResourcesResponseDto": ".list_webhook_resources_response_dto",
+ "ListWebhooksResponseDto": ".list_webhooks_response_dto",
"ManageEntitiesResponse": ".manage_entities_response",
+ "MappableResourceType": ".mappable_resource_type",
"MonitorCitation": ".monitor_citation",
"MonitorJobItem": ".monitor_job_item",
"MonitorListItemDto": ".monitor_list_item_dto",
@@ -145,6 +200,15 @@
"MonitorStatusHistoryResponseDto": ".monitor_status_history_response_dto",
"OwnershipFilter": ".ownership_filter",
"PlanFeature": ".plan_feature",
+ "ProjectListResponseDto": ".project_list_response_dto",
+ "ProjectOverviewCountsDto": ".project_overview_counts_dto",
+ "ProjectOverviewResponseDto": ".project_overview_response_dto",
+ "ProjectOverviewResponseDtoOverview": ".project_overview_response_dto_overview",
+ "ProjectResourceDto": ".project_resource_dto",
+ "ProjectResourceListResponseDto": ".project_resource_list_response_dto",
+ "ProjectResourceType": ".project_resource_type",
+ "ProjectResponseDto": ".project_response_dto",
+ "ProjectSummaryDto": ".project_summary_dto",
"PublicJobStatus": ".public_job_status",
"PullJobResponseDto": ".pull_job_response_dto",
"PullJobResponseDtoDateRange": ".pull_job_response_dto_date_range",
@@ -152,8 +216,12 @@
"PullMonitorResponseDto": ".pull_monitor_response_dto",
"PullMonitorResponseDtoRunInfo": ".pull_monitor_response_dto_run_info",
"Query": ".query",
+ "QueryStatus": ".query_status",
"Record": ".record",
"ReferenceJob": ".reference_job",
+ "RemoveResourceResponseDto": ".remove_resource_response_dto",
+ "ResourceItemDto": ".resource_item_dto",
+ "ResourceResultDto": ".resource_result_dto",
"SharingInfo": ".sharing_info",
"SharingInfoPermission": ".sharing_info_permission",
"SkippedRow": ".skipped_row",
@@ -161,10 +229,15 @@
"StartDate": ".start_date",
"StatusResponseDto": ".status_response_dto",
"SubmitResponseDto": ".submit_response_dto",
+ "Suggestion": ".suggestion",
+ "TestWebhookResponseDto": ".test_webhook_response_dto",
"UpdateMonitorResponseDto": ".update_monitor_response_dto",
+ "UpdateProjectResponseDto": ".update_project_response_dto",
+ "UpdateWebhookResponseDto": ".update_webhook_response_dto",
"UploadCsvToDatasetResponse": ".upload_csv_to_dataset_response",
"UserJob": ".user_job",
"UserJobMode": ".user_job_mode",
+ "ValidateQueryResponseDto": ".validate_query_response_dto",
"ValidationErrorDetail": ".validation_error_detail",
"ValidationErrorDetailLocItem": ".validation_error_detail_loc_item",
"ValidationErrorResponse": ".validation_error_response",
@@ -173,6 +246,9 @@
"WebhookDto": ".webhook_dto",
"WebhookDtoMethod": ".webhook_dto_method",
"WebhookPayload": ".webhook_payload",
+ "WebhookResourceMappingResponseDto": ".webhook_resource_mapping_response_dto",
+ "WebhookResponseDto": ".webhook_response_dto",
+ "WebhookType": ".webhook_type",
}
@@ -198,10 +274,15 @@ def __dir__():
__all__ = [
+ "AddResourceResponseDto",
"AdditionalAttributes",
+ "ApiKeyAuthDto",
+ "AssignWebhookResourceResponseDto",
"BaseRecord",
"BaseRecordEnrichment",
"BaseRecordEnrichmentEnrichmentConfidence",
+ "BasicAuthDto",
+ "BearerAuthDto",
"Citation",
"CompanyAttributes",
"CompanyEnrichmentOutput",
@@ -215,6 +296,8 @@ def __dir__():
"CreateEntityRequest",
"CreateEntityResponse",
"CreateMonitorResponseDto",
+ "CreateProjectResponseDto",
+ "CreateWebhookResponseDto",
"DatasetEntityIdsRequest",
"DatasetEntityListResponse",
"DatasetListResponse",
@@ -225,6 +308,10 @@ def __dir__():
"DatasetStatusHistoryResponse",
"DeleteJobResponseDto",
"DeleteMonitorResponseDto",
+ "DeliveryHistoryItemDto",
+ "DeliveryHistoryResponseDto",
+ "DeliveryMode",
+ "DeliveryStatus",
"EndDate",
"EnrichmentSchema",
"EnrichmentType",
@@ -237,12 +324,18 @@ def __dir__():
"EntityValidationErrorBody",
"Error",
"GetPlanLimitsResponseDto",
+ "GetWebhookResponseDto",
+ "HttpMethod",
"InitializeResponseDto",
+ "IssueType",
"JobStep",
"Limit",
"ListMonitorsResponseDto",
"ListUserJobsResponseDto",
+ "ListWebhookResourcesResponseDto",
+ "ListWebhooksResponseDto",
"ManageEntitiesResponse",
+ "MappableResourceType",
"MonitorCitation",
"MonitorJobItem",
"MonitorListItemDto",
@@ -252,6 +345,15 @@ def __dir__():
"MonitorStatusHistoryResponseDto",
"OwnershipFilter",
"PlanFeature",
+ "ProjectListResponseDto",
+ "ProjectOverviewCountsDto",
+ "ProjectOverviewResponseDto",
+ "ProjectOverviewResponseDtoOverview",
+ "ProjectResourceDto",
+ "ProjectResourceListResponseDto",
+ "ProjectResourceType",
+ "ProjectResponseDto",
+ "ProjectSummaryDto",
"PublicJobStatus",
"PullJobResponseDto",
"PullJobResponseDtoDateRange",
@@ -259,8 +361,12 @@ def __dir__():
"PullMonitorResponseDto",
"PullMonitorResponseDtoRunInfo",
"Query",
+ "QueryStatus",
"Record",
"ReferenceJob",
+ "RemoveResourceResponseDto",
+ "ResourceItemDto",
+ "ResourceResultDto",
"SharingInfo",
"SharingInfoPermission",
"SkippedRow",
@@ -268,10 +374,15 @@ def __dir__():
"StartDate",
"StatusResponseDto",
"SubmitResponseDto",
+ "Suggestion",
+ "TestWebhookResponseDto",
"UpdateMonitorResponseDto",
+ "UpdateProjectResponseDto",
+ "UpdateWebhookResponseDto",
"UploadCsvToDatasetResponse",
"UserJob",
"UserJobMode",
+ "ValidateQueryResponseDto",
"ValidationErrorDetail",
"ValidationErrorDetailLocItem",
"ValidationErrorResponse",
@@ -280,4 +391,7 @@ def __dir__():
"WebhookDto",
"WebhookDtoMethod",
"WebhookPayload",
+ "WebhookResourceMappingResponseDto",
+ "WebhookResponseDto",
+ "WebhookType",
]
diff --git a/src/newscatcher_catchall/types/add_resource_response_dto.py b/src/newscatcher_catchall/types/add_resource_response_dto.py
new file mode 100644
index 0000000..3a36e9e
--- /dev/null
+++ b/src/newscatcher_catchall/types/add_resource_response_dto.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .resource_result_dto import ResourceResultDto
+
+
+class AddResourceResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the overall operation succeeded.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Top-level result message.
+ """
+
+ results: typing.List[ResourceResultDto] = pydantic.Field()
+ """
+ Per-resource outcome, one entry per submitted resource.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/api_key_auth_dto.py b/src/newscatcher_catchall/types/api_key_auth_dto.py
new file mode 100644
index 0000000..898841e
--- /dev/null
+++ b/src/newscatcher_catchall/types/api_key_auth_dto.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class ApiKeyAuthDto(UniversalBaseModel):
+ header: str = pydantic.Field()
+ """
+ HTTP header name for the API key.
+ """
+
+ value: str = pydantic.Field()
+ """
+ API key value.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/assign_webhook_resource_response_dto.py b/src/newscatcher_catchall/types/assign_webhook_resource_response_dto.py
new file mode 100644
index 0000000..dcf4627
--- /dev/null
+++ b/src/newscatcher_catchall/types/assign_webhook_resource_response_dto.py
@@ -0,0 +1,38 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_resource_mapping_response_dto import WebhookResourceMappingResponseDto
+
+
+class AssignWebhookResourceResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Human-readable result message.
+ """
+
+ already_existed: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ True if the assignment already existed before this request.
+ """
+
+ mapping: typing.Optional[WebhookResourceMappingResponseDto] = pydantic.Field(default=None)
+ """
+ The created or existing resource mapping.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/basic_auth_dto.py b/src/newscatcher_catchall/types/basic_auth_dto.py
new file mode 100644
index 0000000..aa8e69c
--- /dev/null
+++ b/src/newscatcher_catchall/types/basic_auth_dto.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class BasicAuthDto(UniversalBaseModel):
+ username: str = pydantic.Field()
+ """
+ Basic auth username.
+ """
+
+ password: str = pydantic.Field()
+ """
+ Basic auth password.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/bearer_auth_dto.py b/src/newscatcher_catchall/types/bearer_auth_dto.py
new file mode 100644
index 0000000..bf86a3f
--- /dev/null
+++ b/src/newscatcher_catchall/types/bearer_auth_dto.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class BearerAuthDto(UniversalBaseModel):
+ token: str = pydantic.Field()
+ """
+ Bearer token sent in the `Authorization` header.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/connected_entity.py b/src/newscatcher_catchall/types/connected_entity.py
index cf9098a..93c9977 100644
--- a/src/newscatcher_catchall/types/connected_entity.py
+++ b/src/newscatcher_catchall/types/connected_entity.py
@@ -50,7 +50,7 @@ class ConnectedEntity(UniversalBaseModel):
"""
The stored attributes for this entity. Present only when attributes exist in the database.
- The field name matches the value of `type` — for example, `"company"` type entities have a `company` field.
+ The field name matches the value of `type` — for example, `"company"` type entities have a `company` field.
"""
if IS_PYDANTIC_V2:
diff --git a/src/newscatcher_catchall/types/create_project_response_dto.py b/src/newscatcher_catchall/types/create_project_response_dto.py
new file mode 100644
index 0000000..a3016f1
--- /dev/null
+++ b/src/newscatcher_catchall/types/create_project_response_dto.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class CreateProjectResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ project_id: str = pydantic.Field()
+ """
+ Project identifier.
+ """
+
+ name: str = pydantic.Field()
+ """
+ Name of the created project.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/create_webhook_response_dto.py b/src/newscatcher_catchall/types/create_webhook_response_dto.py
new file mode 100644
index 0000000..65df7e7
--- /dev/null
+++ b/src/newscatcher_catchall/types/create_webhook_response_dto.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_response_dto import WebhookResponseDto
+
+
+class CreateWebhookResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the webhook was created; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ webhook: typing.Optional[WebhookResponseDto] = pydantic.Field(default=None)
+ """
+ The created webhook object.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/delete_job_response_dto.py b/src/newscatcher_catchall/types/delete_job_response_dto.py
index 17f900f..35eba99 100644
--- a/src/newscatcher_catchall/types/delete_job_response_dto.py
+++ b/src/newscatcher_catchall/types/delete_job_response_dto.py
@@ -9,7 +9,7 @@
class DeleteJobResponseDto(UniversalBaseModel):
success: bool = pydantic.Field()
"""
- Whether the delete operation succeeded.
+ True if the delete operation succeeded; false otherwise.
"""
message: typing.Optional[str] = pydantic.Field(default=None)
diff --git a/src/newscatcher_catchall/types/delete_monitor_response_dto.py b/src/newscatcher_catchall/types/delete_monitor_response_dto.py
index 127791d..b30b7c9 100644
--- a/src/newscatcher_catchall/types/delete_monitor_response_dto.py
+++ b/src/newscatcher_catchall/types/delete_monitor_response_dto.py
@@ -9,7 +9,7 @@
class DeleteMonitorResponseDto(UniversalBaseModel):
success: bool = pydantic.Field()
"""
- Whether the delete operation succeeded.
+ True if the delete operation succeeded; false otherwise.
"""
message: typing.Optional[str] = pydantic.Field(default=None)
diff --git a/src/newscatcher_catchall/types/delivery_history_item_dto.py b/src/newscatcher_catchall/types/delivery_history_item_dto.py
new file mode 100644
index 0000000..7a72f4e
--- /dev/null
+++ b/src/newscatcher_catchall/types/delivery_history_item_dto.py
@@ -0,0 +1,75 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .delivery_status import DeliveryStatus
+from .mappable_resource_type import MappableResourceType
+
+
+class DeliveryHistoryItemDto(UniversalBaseModel):
+ id: int = pydantic.Field()
+ """
+ Delivery record identifier.
+ """
+
+ webhook_id: str = pydantic.Field()
+ """
+ Identifier of the webhook that was dispatched.
+ """
+
+ resource_type: MappableResourceType = pydantic.Field()
+ """
+ Type of the resource that triggered the delivery.
+ """
+
+ resource_id: str = pydantic.Field()
+ """
+ Identifier of the resource that triggered the delivery.
+ """
+
+ additional_info: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Extra context about the triggering event, such as job query or monitor schedule.
+ """
+
+ status_code: int = pydantic.Field()
+ """
+ HTTP response code returned by the webhook endpoint.
+ """
+
+ attempt_number: int = pydantic.Field()
+ """
+ Delivery attempt number. 1 indicates the first attempt.
+ """
+
+ timestamp: dt.datetime = pydantic.Field()
+ """
+ Time of the delivery attempt in ISO 8601 format with UTC timezone.
+ """
+
+ delivery_status: DeliveryStatus = pydantic.Field()
+ """
+ Outcome of this delivery attempt.
+ """
+
+ error_message: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Error detail when `delivery_status` is `FAILED`. Null on success.
+ """
+
+ warning_message: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Non-fatal warning, such as payload truncation notices. Null when no warnings occurred.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/delivery_history_response_dto.py b/src/newscatcher_catchall/types/delivery_history_response_dto.py
new file mode 100644
index 0000000..192245d
--- /dev/null
+++ b/src/newscatcher_catchall/types/delivery_history_response_dto.py
@@ -0,0 +1,54 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .delivery_history_item_dto import DeliveryHistoryItemDto
+from .mappable_resource_type import MappableResourceType
+
+
+class DeliveryHistoryResponseDto(UniversalBaseModel):
+ resource_type: MappableResourceType = pydantic.Field()
+ """
+ Type of the queried resource.
+ """
+
+ resource_id: str = pydantic.Field()
+ """
+ Identifier of the queried resource.
+ """
+
+ total: int = pydantic.Field()
+ """
+ Total number of delivery records for this resource.
+ """
+
+ page: int = pydantic.Field()
+ """
+ Current page number.
+ """
+
+ page_size: int = pydantic.Field()
+ """
+ Number of records per page.
+ """
+
+ total_pages: int = pydantic.Field()
+ """
+ Total number of pages available.
+ """
+
+ items: typing.List[DeliveryHistoryItemDto] = pydantic.Field()
+ """
+ Delivery records on this page, ordered by timestamp descending.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/delivery_mode.py b/src/newscatcher_catchall/types/delivery_mode.py
new file mode 100644
index 0000000..f514b52
--- /dev/null
+++ b/src/newscatcher_catchall/types/delivery_mode.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DeliveryMode = typing.Union[typing.Literal["full", "per_record"], typing.Any]
diff --git a/src/newscatcher_catchall/types/delivery_status.py b/src/newscatcher_catchall/types/delivery_status.py
new file mode 100644
index 0000000..a52b9d6
--- /dev/null
+++ b/src/newscatcher_catchall/types/delivery_status.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DeliveryStatus = typing.Union[typing.Literal["SUCCESS", "FAILED"], typing.Any]
diff --git a/src/newscatcher_catchall/types/get_webhook_response_dto.py b/src/newscatcher_catchall/types/get_webhook_response_dto.py
new file mode 100644
index 0000000..1724b4e
--- /dev/null
+++ b/src/newscatcher_catchall/types/get_webhook_response_dto.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_response_dto import WebhookResponseDto
+
+
+class GetWebhookResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ webhook: typing.Optional[WebhookResponseDto] = pydantic.Field(default=None)
+ """
+ The retrieved webhook object.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/http_method.py b/src/newscatcher_catchall/types/http_method.py
new file mode 100644
index 0000000..ca1a4ac
--- /dev/null
+++ b/src/newscatcher_catchall/types/http_method.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+HttpMethod = typing.Union[typing.Literal["GET", "POST", "PUT", "PATCH", "DELETE"], typing.Any]
diff --git a/src/newscatcher_catchall/types/issue_type.py b/src/newscatcher_catchall/types/issue_type.py
new file mode 100644
index 0000000..78cc394
--- /dev/null
+++ b/src/newscatcher_catchall/types/issue_type.py
@@ -0,0 +1,18 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+IssueType = typing.Union[
+ typing.Literal[
+ "missing_event_type",
+ "too_vague",
+ "too_specific",
+ "wrong_timeframe",
+ "static_content",
+ "article_request",
+ "multiple_event_types",
+ "too_short",
+ "too_long",
+ ],
+ typing.Any,
+]
diff --git a/src/newscatcher_catchall/types/job_step.py b/src/newscatcher_catchall/types/job_step.py
index dabb76e..242691b 100644
--- a/src/newscatcher_catchall/types/job_step.py
+++ b/src/newscatcher_catchall/types/job_step.py
@@ -16,7 +16,7 @@ class JobStep(UniversalBaseModel):
completed: bool = pydantic.Field()
"""
- Whether this step has finished processing.
+ True if this step has finished processing; false otherwise.
"""
if IS_PYDANTIC_V2:
diff --git a/src/newscatcher_catchall/types/list_webhook_resources_response_dto.py b/src/newscatcher_catchall/types/list_webhook_resources_response_dto.py
new file mode 100644
index 0000000..fbb2fb4
--- /dev/null
+++ b/src/newscatcher_catchall/types/list_webhook_resources_response_dto.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_resource_mapping_response_dto import WebhookResourceMappingResponseDto
+
+
+class ListWebhookResourcesResponseDto(UniversalBaseModel):
+ total: int = pydantic.Field()
+ """
+ Total number of resource mappings for this webhook.
+ """
+
+ page: int = pydantic.Field()
+ """
+ Current page number.
+ """
+
+ page_size: int = pydantic.Field()
+ """
+ Number of mappings per page.
+ """
+
+ total_pages: int = pydantic.Field()
+ """
+ Total number of pages available.
+ """
+
+ resources: typing.List[WebhookResourceMappingResponseDto] = pydantic.Field()
+ """
+ Resource mappings on this page.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/list_webhooks_response_dto.py b/src/newscatcher_catchall/types/list_webhooks_response_dto.py
new file mode 100644
index 0000000..d34314c
--- /dev/null
+++ b/src/newscatcher_catchall/types/list_webhooks_response_dto.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_response_dto import WebhookResponseDto
+
+
+class ListWebhooksResponseDto(UniversalBaseModel):
+ total: int = pydantic.Field()
+ """
+ Total number of webhooks in the organization.
+ """
+
+ page: int = pydantic.Field()
+ """
+ Current page number.
+ """
+
+ page_size: int = pydantic.Field()
+ """
+ Number of webhooks per page.
+ """
+
+ total_pages: int = pydantic.Field()
+ """
+ Total number of pages available.
+ """
+
+ webhooks: typing.List[WebhookResponseDto] = pydantic.Field()
+ """
+ Webhooks on this page.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/mappable_resource_type.py b/src/newscatcher_catchall/types/mappable_resource_type.py
new file mode 100644
index 0000000..87d519c
--- /dev/null
+++ b/src/newscatcher_catchall/types/mappable_resource_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+MappableResourceType = typing.Union[typing.Literal["job", "monitor", "monitor_group"], typing.Any]
diff --git a/src/newscatcher_catchall/types/monitor_list_item_dto.py b/src/newscatcher_catchall/types/monitor_list_item_dto.py
index 4a029b9..89be2f2 100644
--- a/src/newscatcher_catchall/types/monitor_list_item_dto.py
+++ b/src/newscatcher_catchall/types/monitor_list_item_dto.py
@@ -27,7 +27,7 @@ class MonitorListItemDto(UniversalBaseModel):
enabled: bool = pydantic.Field()
"""
- Whether the monitor is currently active.
+ True if the monitor is currently active; false otherwise.
"""
schedule: typing.Optional[str] = pydantic.Field(default=None)
diff --git a/src/newscatcher_catchall/types/monitor_status_history_response_dto.py b/src/newscatcher_catchall/types/monitor_status_history_response_dto.py
index 9938bfb..c8891fd 100644
--- a/src/newscatcher_catchall/types/monitor_status_history_response_dto.py
+++ b/src/newscatcher_catchall/types/monitor_status_history_response_dto.py
@@ -10,7 +10,7 @@
class MonitorStatusHistoryResponseDto(UniversalBaseModel):
success: bool = pydantic.Field()
"""
- Whether the request succeeded.
+ True if the request succeeded; false otherwise.
"""
message: typing.Optional[str] = pydantic.Field(default=None)
diff --git a/src/newscatcher_catchall/types/project_list_response_dto.py b/src/newscatcher_catchall/types/project_list_response_dto.py
new file mode 100644
index 0000000..94f8209
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_list_response_dto.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_summary_dto import ProjectSummaryDto
+
+
+class ProjectListResponseDto(UniversalBaseModel):
+ total: int = pydantic.Field()
+ """
+ Total number of projects matching the filter criteria.
+ """
+
+ page: int = pydantic.Field()
+ """
+ Current page number.
+ """
+
+ page_size: int = pydantic.Field()
+ """
+ Number of projects per page.
+ """
+
+ total_pages: int = pydantic.Field()
+ """
+ Total number of pages.
+ """
+
+ projects: typing.List[ProjectSummaryDto] = pydantic.Field()
+ """
+ Projects on this page.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_overview_counts_dto.py b/src/newscatcher_catchall/types/project_overview_counts_dto.py
new file mode 100644
index 0000000..6522734
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_overview_counts_dto.py
@@ -0,0 +1,8 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ProjectOverviewCountsDto = typing.Dict[str, typing.Any]
+"""
+Status breakdown for a single resource type.
+"""
diff --git a/src/newscatcher_catchall/types/project_overview_response_dto.py b/src/newscatcher_catchall/types/project_overview_response_dto.py
new file mode 100644
index 0000000..a05c8d7
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_overview_response_dto.py
@@ -0,0 +1,28 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_overview_response_dto_overview import ProjectOverviewResponseDtoOverview
+
+
+class ProjectOverviewResponseDto(UniversalBaseModel):
+ project_id: str = pydantic.Field()
+ """
+ Project identifier.
+ """
+
+ overview: ProjectOverviewResponseDtoOverview = pydantic.Field()
+ """
+ Resource counts grouped by type.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_overview_response_dto_overview.py b/src/newscatcher_catchall/types/project_overview_response_dto_overview.py
new file mode 100644
index 0000000..e67cdac
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_overview_response_dto_overview.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_overview_counts_dto import ProjectOverviewCountsDto
+
+
+class ProjectOverviewResponseDtoOverview(UniversalBaseModel):
+ """
+ Resource counts grouped by type.
+ """
+
+ jobs: ProjectOverviewCountsDto
+ monitors: ProjectOverviewCountsDto
+ datasets: ProjectOverviewCountsDto
+ monitor_groups: ProjectOverviewCountsDto
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_resource_dto.py b/src/newscatcher_catchall/types/project_resource_dto.py
new file mode 100644
index 0000000..881aa8e
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_resource_dto.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_resource_type import ProjectResourceType
+
+
+class ProjectResourceDto(UniversalBaseModel):
+ """
+ A resource assigned to a project.
+ """
+
+ resource_type: ProjectResourceType
+ resource_id: str = pydantic.Field()
+ """
+ Resource identifier.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Resource display name. For jobs, this is the original query
+ string. For monitors and datasets, this is the resource name.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Resource creation timestamp.
+ """
+
+ metadata: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Additional resource-specific metadata.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_resource_list_response_dto.py b/src/newscatcher_catchall/types/project_resource_list_response_dto.py
new file mode 100644
index 0000000..35fb9d4
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_resource_list_response_dto.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_resource_dto import ProjectResourceDto
+
+
+class ProjectResourceListResponseDto(UniversalBaseModel):
+ total: int = pydantic.Field()
+ """
+ Total number of resources assigned to the project.
+ """
+
+ page: int = pydantic.Field()
+ """
+ Current page number.
+ """
+
+ page_size: int = pydantic.Field()
+ """
+ Number of resources per page.
+ """
+
+ total_pages: int = pydantic.Field()
+ """
+ Total number of pages.
+ """
+
+ resources: typing.List[ProjectResourceDto] = pydantic.Field()
+ """
+ Resources on this page.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_resource_type.py b/src/newscatcher_catchall/types/project_resource_type.py
new file mode 100644
index 0000000..3169e29
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_resource_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ProjectResourceType = typing.Union[typing.Literal["job", "monitor", "dataset", "monitor_group"], typing.Any]
diff --git a/src/newscatcher_catchall/types/project_response_dto.py b/src/newscatcher_catchall/types/project_response_dto.py
new file mode 100644
index 0000000..22b2588
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_response_dto.py
@@ -0,0 +1,58 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class ProjectResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ project_id: str = pydantic.Field()
+ """
+ Project identifier.
+ """
+
+ name: str = pydantic.Field()
+ """
+ Project name.
+ """
+
+ description: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Project description.
+ """
+
+ resources_count: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Number of resources assigned to this project.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Project creation timestamp.
+ """
+
+ updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Timestamp of the last update.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/project_summary_dto.py b/src/newscatcher_catchall/types/project_summary_dto.py
new file mode 100644
index 0000000..52af56b
--- /dev/null
+++ b/src/newscatcher_catchall/types/project_summary_dto.py
@@ -0,0 +1,52 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class ProjectSummaryDto(UniversalBaseModel):
+ """
+ Abbreviated project object returned in list responses.
+ """
+
+ project_id: str = pydantic.Field()
+ """
+ Project identifier.
+ """
+
+ name: str = pydantic.Field()
+ """
+ Project name.
+ """
+
+ description: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Project description.
+ """
+
+ resources_count: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Number of resources assigned to this project.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Project creation timestamp.
+ """
+
+ updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Timestamp of the last update.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/query_status.py b/src/newscatcher_catchall/types/query_status.py
new file mode 100644
index 0000000..88c8c76
--- /dev/null
+++ b/src/newscatcher_catchall/types/query_status.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+QueryStatus = typing.Union[typing.Literal["good", "needs_work", "critical"], typing.Any]
diff --git a/src/newscatcher_catchall/types/remove_resource_response_dto.py b/src/newscatcher_catchall/types/remove_resource_response_dto.py
new file mode 100644
index 0000000..cfd5e8f
--- /dev/null
+++ b/src/newscatcher_catchall/types/remove_resource_response_dto.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class RemoveResourceResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/resource_item_dto.py b/src/newscatcher_catchall/types/resource_item_dto.py
new file mode 100644
index 0000000..15527fc
--- /dev/null
+++ b/src/newscatcher_catchall/types/resource_item_dto.py
@@ -0,0 +1,24 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .project_resource_type import ProjectResourceType
+
+
+class ResourceItemDto(UniversalBaseModel):
+ resource_type: ProjectResourceType
+ resource_id: str = pydantic.Field()
+ """
+ ID of the resource to add.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/resource_result_dto.py b/src/newscatcher_catchall/types/resource_result_dto.py
new file mode 100644
index 0000000..6e66192
--- /dev/null
+++ b/src/newscatcher_catchall/types/resource_result_dto.py
@@ -0,0 +1,42 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class ResourceResultDto(UniversalBaseModel):
+ resource_type: str = pydantic.Field()
+ """
+ Type of the resource.
+ """
+
+ resource_id: str = pydantic.Field()
+ """
+ Resource identifier.
+ """
+
+ success: bool = pydantic.Field()
+ """
+ True if this resource was processed successfully.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Per-resource result message.
+ """
+
+ already_exists: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ True if the resource is already assigned to this project.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/suggestion.py b/src/newscatcher_catchall/types/suggestion.py
new file mode 100644
index 0000000..03ed5f4
--- /dev/null
+++ b/src/newscatcher_catchall/types/suggestion.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .issue_type import IssueType
+
+
+class Suggestion(UniversalBaseModel):
+ """
+ Actionable recommendation for improving a query.
+ """
+
+ issue: IssueType = pydantic.Field()
+ """
+ The issue this suggestion addresses.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Specific guidance for improving the query.
+ """
+
+ example: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Revised query demonstrating the suggested improvement.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/test_webhook_response_dto.py b/src/newscatcher_catchall/types/test_webhook_response_dto.py
new file mode 100644
index 0000000..dd0779f
--- /dev/null
+++ b/src/newscatcher_catchall/types/test_webhook_response_dto.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class TestWebhookResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the test delivery received a 2xx response; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ http_status_code: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ HTTP status code returned by the webhook endpoint.
+ """
+
+ response_body: typing.Optional[typing.Any] = pydantic.Field(default=None)
+ """
+ Response body returned by the webhook endpoint. Type varies by target.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/update_project_response_dto.py b/src/newscatcher_catchall/types/update_project_response_dto.py
new file mode 100644
index 0000000..e5d68c7
--- /dev/null
+++ b/src/newscatcher_catchall/types/update_project_response_dto.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class UpdateProjectResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the operation succeeded; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ project_id: str = pydantic.Field()
+ """
+ Project identifier.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/update_webhook_response_dto.py b/src/newscatcher_catchall/types/update_webhook_response_dto.py
new file mode 100644
index 0000000..0c84d12
--- /dev/null
+++ b/src/newscatcher_catchall/types/update_webhook_response_dto.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .webhook_response_dto import WebhookResponseDto
+
+
+class UpdateWebhookResponseDto(UniversalBaseModel):
+ success: bool = pydantic.Field()
+ """
+ True if the webhook was updated; false otherwise.
+ """
+
+ message: str = pydantic.Field()
+ """
+ Human-readable result message.
+ """
+
+ webhook: typing.Optional[WebhookResponseDto] = pydantic.Field(default=None)
+ """
+ The updated webhook object.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/validate_query_response_dto.py b/src/newscatcher_catchall/types/validate_query_response_dto.py
new file mode 100644
index 0000000..359f8ea
--- /dev/null
+++ b/src/newscatcher_catchall/types/validate_query_response_dto.py
@@ -0,0 +1,54 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .issue_type import IssueType
+from .query_status import QueryStatus
+from .suggestion import Suggestion
+
+
+class ValidateQueryResponseDto(UniversalBaseModel):
+ """
+ Query quality assessment returned by the validate endpoint.
+ """
+
+ status: QueryStatus = pydantic.Field()
+ """
+ Overall quality level of the query.
+ """
+
+ title: str = pydantic.Field()
+ """
+ Short headline summarising the assessment.
+ """
+
+ description: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Plain-language explanation of the assessment result.
+ """
+
+ issues: typing.Optional[typing.List[IssueType]] = pydantic.Field(default=None)
+ """
+ Issues identified in the query. Empty when `status` is `good`.
+ """
+
+ suggestions: typing.Optional[typing.List[Suggestion]] = pydantic.Field(default=None)
+ """
+ Actionable recommendations for each identified issue. Empty when `status` is `good`. Each suggestion corresponds to one entry in `issues`.
+ """
+
+ confidence: float = pydantic.Field()
+ """
+ Confidence score for this assessment.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/webhook_resource_mapping_response_dto.py b/src/newscatcher_catchall/types/webhook_resource_mapping_response_dto.py
new file mode 100644
index 0000000..65b5d2a
--- /dev/null
+++ b/src/newscatcher_catchall/types/webhook_resource_mapping_response_dto.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class WebhookResourceMappingResponseDto(UniversalBaseModel):
+ id: str = pydantic.Field()
+ """
+ Mapping identifier.
+ """
+
+ webhook_id: str = pydantic.Field()
+ """
+ Webhook identifier.
+ """
+
+ resource_type: str = pydantic.Field()
+ """
+ Type of the assigned resource.
+ """
+
+ resource_id: str = pydantic.Field()
+ """
+ Identifier of the assigned resource.
+ """
+
+ assigned_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Timestamp when the resource was assigned in ISO 8601 format with UTC timezone.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/webhook_response_dto.py b/src/newscatcher_catchall/types/webhook_response_dto.py
new file mode 100644
index 0000000..f71e80f
--- /dev/null
+++ b/src/newscatcher_catchall/types/webhook_response_dto.py
@@ -0,0 +1,79 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .delivery_mode import DeliveryMode
+from .http_method import HttpMethod
+from .webhook_type import WebhookType
+
+
+class WebhookResponseDto(UniversalBaseModel):
+ id: str = pydantic.Field()
+ """
+ Webhook identifier.
+ """
+
+ name: str = pydantic.Field()
+ """
+ Human-readable label for this webhook.
+ """
+
+ url: str = pydantic.Field()
+ """
+ Destination URL that receives the payload.
+ """
+
+ type: WebhookType
+ delivery_mode: DeliveryMode
+ method: HttpMethod
+ headers: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None)
+ """
+ Custom HTTP headers forwarded with each delivery.
+ """
+
+ params: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None)
+ """
+ Query parameters appended to the webhook URL.
+ """
+
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Custom payload transformation configuration. Used only when `type` is `custom`.
+ """
+
+ is_active: bool = pydantic.Field()
+ """
+ True if the webhook is active; false otherwise.
+ """
+
+ organization_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Organization that owns this webhook.
+ """
+
+ created_by_user_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ ID of the user who created this webhook.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Webhook creation timestamp in ISO 8601 format with UTC timezone.
+ """
+
+ updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ Timestamp of the last update in ISO 8601 format with UTC timezone.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/newscatcher_catchall/types/webhook_type.py b/src/newscatcher_catchall/types/webhook_type.py
new file mode 100644
index 0000000..7aa9444
--- /dev/null
+++ b/src/newscatcher_catchall/types/webhook_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+WebhookType = typing.Union[typing.Literal["generic", "slack", "teams", "custom"], typing.Any]
diff --git a/src/newscatcher_catchall/webhooks/__init__.py b/src/newscatcher_catchall/webhooks/__init__.py
new file mode 100644
index 0000000..d6a6aa7
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/__init__.py
@@ -0,0 +1,61 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ CreateWebhookRequestDtoAuth,
+ CreateWebhookRequestDtoAuth_ApiKey,
+ CreateWebhookRequestDtoAuth_Basic,
+ CreateWebhookRequestDtoAuth_Bearer,
+ UpdateWebhookRequestDtoAuth,
+ UpdateWebhookRequestDtoAuth_ApiKey,
+ UpdateWebhookRequestDtoAuth_Basic,
+ UpdateWebhookRequestDtoAuth_Bearer,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "CreateWebhookRequestDtoAuth": ".types",
+ "CreateWebhookRequestDtoAuth_ApiKey": ".types",
+ "CreateWebhookRequestDtoAuth_Basic": ".types",
+ "CreateWebhookRequestDtoAuth_Bearer": ".types",
+ "UpdateWebhookRequestDtoAuth": ".types",
+ "UpdateWebhookRequestDtoAuth_ApiKey": ".types",
+ "UpdateWebhookRequestDtoAuth_Basic": ".types",
+ "UpdateWebhookRequestDtoAuth_Bearer": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "CreateWebhookRequestDtoAuth",
+ "CreateWebhookRequestDtoAuth_ApiKey",
+ "CreateWebhookRequestDtoAuth_Basic",
+ "CreateWebhookRequestDtoAuth_Bearer",
+ "UpdateWebhookRequestDtoAuth",
+ "UpdateWebhookRequestDtoAuth_ApiKey",
+ "UpdateWebhookRequestDtoAuth_Basic",
+ "UpdateWebhookRequestDtoAuth_Bearer",
+]
diff --git a/src/newscatcher_catchall/webhooks/client.py b/src/newscatcher_catchall/webhooks/client.py
new file mode 100644
index 0000000..ec01532
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/client.py
@@ -0,0 +1,1336 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.request_options import RequestOptions
+from ..types.assign_webhook_resource_response_dto import AssignWebhookResourceResponseDto
+from ..types.create_webhook_response_dto import CreateWebhookResponseDto
+from ..types.delivery_history_response_dto import DeliveryHistoryResponseDto
+from ..types.delivery_mode import DeliveryMode
+from ..types.get_webhook_response_dto import GetWebhookResponseDto
+from ..types.http_method import HttpMethod
+from ..types.list_webhook_resources_response_dto import ListWebhookResourcesResponseDto
+from ..types.list_webhooks_response_dto import ListWebhooksResponseDto
+from ..types.mappable_resource_type import MappableResourceType
+from ..types.test_webhook_response_dto import TestWebhookResponseDto
+from ..types.update_webhook_response_dto import UpdateWebhookResponseDto
+from ..types.webhook_type import WebhookType
+from .raw_client import AsyncRawWebhooksClient, RawWebhooksClient
+from .types.create_webhook_request_dto_auth import CreateWebhookRequestDtoAuth
+from .types.update_webhook_request_dto_auth import UpdateWebhookRequestDtoAuth
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class WebhooksClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawWebhooksClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawWebhooksClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawWebhooksClient
+ """
+ return self._raw_client
+
+ def list_webhooks(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhooksResponseDto:
+ """
+ Returns a paginated list of webhooks belonging to the organization.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ search : typing.Optional[str]
+ Filter results by text (case-insensitive substring match).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhooksResponseDto
+ Webhooks retrieved successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.list_webhooks()
+ """
+ _response = self._raw_client.list_webhooks(
+ page=page, page_size=page_size, search=search, request_options=request_options
+ )
+ return _response.data
+
+ def create_webhook(
+ self,
+ *,
+ name: str,
+ url: str,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[CreateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CreateWebhookResponseDto:
+ """
+ Creates a new webhook endpoint for the organization.
+
+ Parameters
+ ----------
+ name : str
+ Human-readable label for this webhook.
+
+ url : str
+ Destination URL that receives the payload. Must use HTTPS. IP addresses are not accepted.
+
+ Type-specific URL requirements:
+ - `slack`: Must start with `https://hooks.slack.com/`.
+ - `teams`: Hostname must match `*.webhook.office.com` or `*.webhook.office365.com`.
+ - `generic`: Any valid HTTPS domain.
+ - `custom`: Any valid HTTPS domain.
+
+ When `type` is omitted, it is auto-detected from the URL.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Custom HTTP headers forwarded with each delivery.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Query parameters appended to the webhook URL.
+
+ auth : typing.Optional[CreateWebhookRequestDtoAuth]
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload transformation configuration. Required only when `type` is `custom`.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CreateWebhookResponseDto
+ Webhook created successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.create_webhook(
+ name="Layoffs Alert",
+ url="https://hooks.slack.com/services/T000/B000/xxx",
+ type="slack",
+ delivery_mode="full",
+ )
+ """
+ _response = self._raw_client.create_webhook(
+ name=name,
+ url=url,
+ type=type,
+ delivery_mode=delivery_mode,
+ method=method,
+ headers=headers,
+ params=params,
+ auth=auth,
+ formatter_config=formatter_config,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def get_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> GetWebhookResponseDto:
+ """
+ Returns the full configuration of a single webhook by ID.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ GetWebhookResponseDto
+ Webhook retrieved successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.get_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+ """
+ _response = self._raw_client.get_webhook(webhook_id, request_options=request_options)
+ return _response.data
+
+ def delete_webhook(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
+ """
+ Permanently deletes a webhook and removes all resource assignments.
+
+ Assigned jobs and monitors no longer trigger delivery to this webhook. This operation cannot be undone.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.delete_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+ """
+ _response = self._raw_client.delete_webhook(webhook_id, request_options=request_options)
+ return _response.data
+
+ def update_webhook(
+ self,
+ webhook_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ url: typing.Optional[str] = OMIT,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[UpdateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ is_active: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> UpdateWebhookResponseDto:
+ """
+ Updates one or more fields of an existing webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ name : typing.Optional[str]
+ Updated webhook name.
+
+ url : typing.Optional[str]
+ Updated destination URL. Must use HTTPS. Type-specific URL rules apply.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Updated HTTP headers. Replaces existing headers entirely.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Updated query parameters. Replaces existing params entirely.
+
+ auth : typing.Optional[UpdateWebhookRequestDtoAuth]
+ Updated authentication configuration. Replaces existing auth entirely.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Updated formatter configuration.
+
+ is_active : typing.Optional[bool]
+ Set to `false` to disable delivery without deleting the webhook.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UpdateWebhookResponseDto
+ Webhook updated successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.update_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ name="Layoffs Alert (EU)",
+ is_active=False,
+ )
+ """
+ _response = self._raw_client.update_webhook(
+ webhook_id,
+ name=name,
+ url=url,
+ type=type,
+ delivery_mode=delivery_mode,
+ method=method,
+ headers=headers,
+ params=params,
+ auth=auth,
+ formatter_config=formatter_config,
+ is_active=is_active,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def test_webhook(
+ self,
+ webhook_id: str,
+ *,
+ payload: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> TestWebhookResponseDto:
+ """
+ Sends a test HTTP request to the webhook URL using the webhook's configured method, headers, and auth. Returns the response from the target endpoint.
+
+ Use this to verify URL reachability and authentication before attaching the webhook to a live job or monitor.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ payload : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload to send in the test request. If omitted, a synthetic
+ test payload is sent.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ TestWebhookResponseDto
+ Test delivery attempted. Check `success` and `http_status_code` for the outcome.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.test_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ payload={"test": True, "message": "CatchAll webhook test"},
+ )
+ """
+ _response = self._raw_client.test_webhook(webhook_id, payload=payload, request_options=request_options)
+ return _response.data
+
+ def list_webhook_resources(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: typing.Optional[MappableResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhookResourcesResponseDto:
+ """
+ Returns a paginated list of resources currently assigned to this webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : typing.Optional[MappableResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of assignments per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhookResourcesResponseDto
+ Webhook resource assignments retrieved successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.list_webhook_resources(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+ """
+ _response = self._raw_client.list_webhook_resources(
+ webhook_id, resource_type=resource_type, page=page, page_size=page_size, request_options=request_options
+ )
+ return _response.data
+
+ def assign_webhook_resource(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AssignWebhookResourceResponseDto:
+ """
+ Attaches a job, monitor, or monitor group to the webhook. When the
+ resource completes, the webhook receives a delivery.
+
+ A single webhook can be assigned to multiple resources. Each resource
+ can have up to 5 webhooks assigned.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+ Type of resource to assign.
+
+ resource_id : str
+ ID of the resource to assign.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AssignWebhookResourceResponseDto
+ Resource assigned to webhook.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.assign_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="monitor",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+ """
+ _response = self._raw_client.assign_webhook_resource(
+ webhook_id, resource_type=resource_type, resource_id=resource_id, request_options=request_options
+ )
+ return _response.data
+
+ def remove_webhook_resource(
+ self,
+ webhook_id: str,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> None:
+ """
+ Detaches a resource from this webhook. Completions of the resource no longer trigger delivery to this webhook.
+
+ The webhook and the resource itself are not deleted.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.remove_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+ """
+ _response = self._raw_client.remove_webhook_resource(
+ webhook_id, resource_type, resource_id, request_options=request_options
+ )
+ return _response.data
+
+ def list_webhooks_for_resource(
+ self,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ is_active: typing.Optional[bool] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhooksResponseDto:
+ """
+ Returns all webhooks currently assigned to the given resource.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ is_active : typing.Optional[bool]
+ Filter by active status. Omit to return webhooks regardless of status.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhooksResponseDto
+ Webhooks for resource retrieved successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.list_webhooks_for_resource(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+ """
+ _response = self._raw_client.list_webhooks_for_resource(
+ resource_type,
+ resource_id,
+ is_active=is_active,
+ page=page,
+ page_size=page_size,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def get_webhook_delivery_history(
+ self,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeliveryHistoryResponseDto:
+ """
+ Returns a paginated delivery log for a given resource, ordered by timestamp descending.
+
+ Each record shows the webhook dispatched, the HTTP status code returned, delivery outcome, and any error or warning messages. Use this to debug failed deliveries or audit dispatch activity.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+ Type of the resource to retrieve delivery history for.
+
+ resource_id : str
+ Identifier of the resource to retrieve delivery history for.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeliveryHistoryResponseDto
+ Webhook delivery history retrieved successfully.
+
+ Examples
+ --------
+ from newscatcher_catchall import CatchAllApi
+
+ client = CatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+ client.webhooks.get_webhook_delivery_history(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+ """
+ _response = self._raw_client.get_webhook_delivery_history(
+ resource_type=resource_type,
+ resource_id=resource_id,
+ page=page,
+ page_size=page_size,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncWebhooksClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawWebhooksClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawWebhooksClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawWebhooksClient
+ """
+ return self._raw_client
+
+ async def list_webhooks(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhooksResponseDto:
+ """
+ Returns a paginated list of webhooks belonging to the organization.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ search : typing.Optional[str]
+ Filter results by text (case-insensitive substring match).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhooksResponseDto
+ Webhooks retrieved successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.list_webhooks()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list_webhooks(
+ page=page, page_size=page_size, search=search, request_options=request_options
+ )
+ return _response.data
+
+ async def create_webhook(
+ self,
+ *,
+ name: str,
+ url: str,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[CreateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CreateWebhookResponseDto:
+ """
+ Creates a new webhook endpoint for the organization.
+
+ Parameters
+ ----------
+ name : str
+ Human-readable label for this webhook.
+
+ url : str
+ Destination URL that receives the payload. Must use HTTPS. IP addresses are not accepted.
+
+ Type-specific URL requirements:
+ - `slack`: Must start with `https://hooks.slack.com/`.
+ - `teams`: Hostname must match `*.webhook.office.com` or `*.webhook.office365.com`.
+ - `generic`: Any valid HTTPS domain.
+ - `custom`: Any valid HTTPS domain.
+
+ When `type` is omitted, it is auto-detected from the URL.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Custom HTTP headers forwarded with each delivery.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Query parameters appended to the webhook URL.
+
+ auth : typing.Optional[CreateWebhookRequestDtoAuth]
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload transformation configuration. Required only when `type` is `custom`.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CreateWebhookResponseDto
+ Webhook created successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.create_webhook(
+ name="Layoffs Alert",
+ url="https://hooks.slack.com/services/T000/B000/xxx",
+ type="slack",
+ delivery_mode="full",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create_webhook(
+ name=name,
+ url=url,
+ type=type,
+ delivery_mode=delivery_mode,
+ method=method,
+ headers=headers,
+ params=params,
+ auth=auth,
+ formatter_config=formatter_config,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def get_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> GetWebhookResponseDto:
+ """
+ Returns the full configuration of a single webhook by ID.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ GetWebhookResponseDto
+ Webhook retrieved successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.get_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_webhook(webhook_id, request_options=request_options)
+ return _response.data
+
+ async def delete_webhook(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
+ """
+ Permanently deletes a webhook and removes all resource assignments.
+
+ Assigned jobs and monitors no longer trigger delivery to this webhook. This operation cannot be undone.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.delete_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.delete_webhook(webhook_id, request_options=request_options)
+ return _response.data
+
+ async def update_webhook(
+ self,
+ webhook_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ url: typing.Optional[str] = OMIT,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[UpdateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ is_active: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> UpdateWebhookResponseDto:
+ """
+ Updates one or more fields of an existing webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ name : typing.Optional[str]
+ Updated webhook name.
+
+ url : typing.Optional[str]
+ Updated destination URL. Must use HTTPS. Type-specific URL rules apply.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Updated HTTP headers. Replaces existing headers entirely.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Updated query parameters. Replaces existing params entirely.
+
+ auth : typing.Optional[UpdateWebhookRequestDtoAuth]
+ Updated authentication configuration. Replaces existing auth entirely.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Updated formatter configuration.
+
+ is_active : typing.Optional[bool]
+ Set to `false` to disable delivery without deleting the webhook.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UpdateWebhookResponseDto
+ Webhook updated successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.update_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ name="Layoffs Alert (EU)",
+ is_active=False,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.update_webhook(
+ webhook_id,
+ name=name,
+ url=url,
+ type=type,
+ delivery_mode=delivery_mode,
+ method=method,
+ headers=headers,
+ params=params,
+ auth=auth,
+ formatter_config=formatter_config,
+ is_active=is_active,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def test_webhook(
+ self,
+ webhook_id: str,
+ *,
+ payload: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> TestWebhookResponseDto:
+ """
+ Sends a test HTTP request to the webhook URL using the webhook's configured method, headers, and auth. Returns the response from the target endpoint.
+
+ Use this to verify URL reachability and authentication before attaching the webhook to a live job or monitor.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ payload : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload to send in the test request. If omitted, a synthetic
+ test payload is sent.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ TestWebhookResponseDto
+ Test delivery attempted. Check `success` and `http_status_code` for the outcome.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.test_webhook(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ payload={"test": True, "message": "CatchAll webhook test"},
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.test_webhook(webhook_id, payload=payload, request_options=request_options)
+ return _response.data
+
+ async def list_webhook_resources(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: typing.Optional[MappableResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhookResourcesResponseDto:
+ """
+ Returns a paginated list of resources currently assigned to this webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : typing.Optional[MappableResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of assignments per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhookResourcesResponseDto
+ Webhook resource assignments retrieved successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.list_webhook_resources(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list_webhook_resources(
+ webhook_id, resource_type=resource_type, page=page, page_size=page_size, request_options=request_options
+ )
+ return _response.data
+
+ async def assign_webhook_resource(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AssignWebhookResourceResponseDto:
+ """
+ Attaches a job, monitor, or monitor group to the webhook. When the
+ resource completes, the webhook receives a delivery.
+
+ A single webhook can be assigned to multiple resources. Each resource
+ can have up to 5 webhooks assigned.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+ Type of resource to assign.
+
+ resource_id : str
+ ID of the resource to assign.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AssignWebhookResourceResponseDto
+ Resource assigned to webhook.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.assign_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="monitor",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.assign_webhook_resource(
+ webhook_id, resource_type=resource_type, resource_id=resource_id, request_options=request_options
+ )
+ return _response.data
+
+ async def remove_webhook_resource(
+ self,
+ webhook_id: str,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> None:
+ """
+ Detaches a resource from this webhook. Completions of the resource no longer trigger delivery to this webhook.
+
+ The webhook and the resource itself are not deleted.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.remove_webhook_resource(
+ webhook_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.remove_webhook_resource(
+ webhook_id, resource_type, resource_id, request_options=request_options
+ )
+ return _response.data
+
+ async def list_webhooks_for_resource(
+ self,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ is_active: typing.Optional[bool] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ListWebhooksResponseDto:
+ """
+ Returns all webhooks currently assigned to the given resource.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ is_active : typing.Optional[bool]
+ Filter by active status. Omit to return webhooks regardless of status.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ListWebhooksResponseDto
+ Webhooks for resource retrieved successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.list_webhooks_for_resource(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list_webhooks_for_resource(
+ resource_type,
+ resource_id,
+ is_active=is_active,
+ page=page,
+ page_size=page_size,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def get_webhook_delivery_history(
+ self,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeliveryHistoryResponseDto:
+ """
+ Returns a paginated delivery log for a given resource, ordered by timestamp descending.
+
+ Each record shows the webhook dispatched, the HTTP status code returned, delivery outcome, and any error or warning messages. Use this to debug failed deliveries or audit dispatch activity.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+ Type of the resource to retrieve delivery history for.
+
+ resource_id : str
+ Identifier of the resource to retrieve delivery history for.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeliveryHistoryResponseDto
+ Webhook delivery history retrieved successfully.
+
+ Examples
+ --------
+ import asyncio
+
+ from newscatcher_catchall import AsyncCatchAllApi
+
+ client = AsyncCatchAllApi(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.webhooks.get_webhook_delivery_history(
+ resource_type="job",
+ resource_id="3fec5b07-8786-46d7-9486-d43ff67eccd4",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_webhook_delivery_history(
+ resource_type=resource_type,
+ resource_id=resource_id,
+ page=page,
+ page_size=page_size,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/newscatcher_catchall/webhooks/raw_client.py b/src/newscatcher_catchall/webhooks/raw_client.py
new file mode 100644
index 0000000..8feaaa6
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/raw_client.py
@@ -0,0 +1,2127 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from ..core.api_error import ApiError
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
+from ..core.pydantic_utilities import parse_obj_as
+from ..core.request_options import RequestOptions
+from ..core.serialization import convert_and_respect_annotation_metadata
+from ..errors.bad_request_error import BadRequestError
+from ..errors.forbidden_error import ForbiddenError
+from ..errors.not_found_error import NotFoundError
+from ..errors.unprocessable_entity_error import UnprocessableEntityError
+from ..types.assign_webhook_resource_response_dto import AssignWebhookResourceResponseDto
+from ..types.create_webhook_response_dto import CreateWebhookResponseDto
+from ..types.delivery_history_response_dto import DeliveryHistoryResponseDto
+from ..types.delivery_mode import DeliveryMode
+from ..types.error import Error
+from ..types.get_webhook_response_dto import GetWebhookResponseDto
+from ..types.http_method import HttpMethod
+from ..types.list_webhook_resources_response_dto import ListWebhookResourcesResponseDto
+from ..types.list_webhooks_response_dto import ListWebhooksResponseDto
+from ..types.mappable_resource_type import MappableResourceType
+from ..types.test_webhook_response_dto import TestWebhookResponseDto
+from ..types.update_webhook_response_dto import UpdateWebhookResponseDto
+from ..types.validation_error_response import ValidationErrorResponse
+from ..types.webhook_type import WebhookType
+from .types.create_webhook_request_dto_auth import CreateWebhookRequestDtoAuth
+from .types.update_webhook_request_dto_auth import UpdateWebhookRequestDtoAuth
+from pydantic import ValidationError
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawWebhooksClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list_webhooks(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ListWebhooksResponseDto]:
+ """
+ Returns a paginated list of webhooks belonging to the organization.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ search : typing.Optional[str]
+ Filter results by text (case-insensitive substring match).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ListWebhooksResponseDto]
+ Webhooks retrieved successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/webhooks",
+ method="GET",
+ params={
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhooksResponseDto,
+ parse_obj_as(
+ type_=ListWebhooksResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def create_webhook(
+ self,
+ *,
+ name: str,
+ url: str,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[CreateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[CreateWebhookResponseDto]:
+ """
+ Creates a new webhook endpoint for the organization.
+
+ Parameters
+ ----------
+ name : str
+ Human-readable label for this webhook.
+
+ url : str
+ Destination URL that receives the payload. Must use HTTPS. IP addresses are not accepted.
+
+ Type-specific URL requirements:
+ - `slack`: Must start with `https://hooks.slack.com/`.
+ - `teams`: Hostname must match `*.webhook.office.com` or `*.webhook.office365.com`.
+ - `generic`: Any valid HTTPS domain.
+ - `custom`: Any valid HTTPS domain.
+
+ When `type` is omitted, it is auto-detected from the URL.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Custom HTTP headers forwarded with each delivery.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Query parameters appended to the webhook URL.
+
+ auth : typing.Optional[CreateWebhookRequestDtoAuth]
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload transformation configuration. Required only when `type` is `custom`.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[CreateWebhookResponseDto]
+ Webhook created successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/webhooks",
+ method="POST",
+ json={
+ "name": name,
+ "url": url,
+ "type": type,
+ "delivery_mode": delivery_mode,
+ "method": method,
+ "headers": headers,
+ "params": params,
+ "auth": convert_and_respect_annotation_metadata(
+ object_=auth, annotation=CreateWebhookRequestDtoAuth, direction="write"
+ ),
+ "formatter_config": formatter_config,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CreateWebhookResponseDto,
+ parse_obj_as(
+ type_=CreateWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def get_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[GetWebhookResponseDto]:
+ """
+ Returns the full configuration of a single webhook by ID.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[GetWebhookResponseDto]
+ Webhook retrieved successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ GetWebhookResponseDto,
+ parse_obj_as(
+ type_=GetWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def delete_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[None]:
+ """
+ Permanently deletes a webhook and removes all resource assignments.
+
+ Assigned jobs and monitors no longer trigger delivery to this webhook. This operation cannot be undone.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def update_webhook(
+ self,
+ webhook_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ url: typing.Optional[str] = OMIT,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[UpdateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ is_active: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[UpdateWebhookResponseDto]:
+ """
+ Updates one or more fields of an existing webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ name : typing.Optional[str]
+ Updated webhook name.
+
+ url : typing.Optional[str]
+ Updated destination URL. Must use HTTPS. Type-specific URL rules apply.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Updated HTTP headers. Replaces existing headers entirely.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Updated query parameters. Replaces existing params entirely.
+
+ auth : typing.Optional[UpdateWebhookRequestDtoAuth]
+ Updated authentication configuration. Replaces existing auth entirely.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Updated formatter configuration.
+
+ is_active : typing.Optional[bool]
+ Set to `false` to disable delivery without deleting the webhook.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[UpdateWebhookResponseDto]
+ Webhook updated successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="PATCH",
+ json={
+ "name": name,
+ "url": url,
+ "type": type,
+ "delivery_mode": delivery_mode,
+ "method": method,
+ "headers": headers,
+ "params": params,
+ "auth": convert_and_respect_annotation_metadata(
+ object_=auth, annotation=UpdateWebhookRequestDtoAuth, direction="write"
+ ),
+ "formatter_config": formatter_config,
+ "is_active": is_active,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UpdateWebhookResponseDto,
+ parse_obj_as(
+ type_=UpdateWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def test_webhook(
+ self,
+ webhook_id: str,
+ *,
+ payload: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[TestWebhookResponseDto]:
+ """
+ Sends a test HTTP request to the webhook URL using the webhook's configured method, headers, and auth. Returns the response from the target endpoint.
+
+ Use this to verify URL reachability and authentication before attaching the webhook to a live job or monitor.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ payload : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload to send in the test request. If omitted, a synthetic
+ test payload is sent.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[TestWebhookResponseDto]
+ Test delivery attempted. Check `success` and `http_status_code` for the outcome.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/test",
+ method="POST",
+ json={
+ "payload": payload,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ TestWebhookResponseDto,
+ parse_obj_as(
+ type_=TestWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def list_webhook_resources(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: typing.Optional[MappableResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ListWebhookResourcesResponseDto]:
+ """
+ Returns a paginated list of resources currently assigned to this webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : typing.Optional[MappableResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of assignments per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ListWebhookResourcesResponseDto]
+ Webhook resource assignments retrieved successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhookResourcesResponseDto,
+ parse_obj_as(
+ type_=ListWebhookResourcesResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def assign_webhook_resource(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[AssignWebhookResourceResponseDto]:
+ """
+ Attaches a job, monitor, or monitor group to the webhook. When the
+ resource completes, the webhook receives a delivery.
+
+ A single webhook can be assigned to multiple resources. Each resource
+ can have up to 5 webhooks assigned.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+ Type of resource to assign.
+
+ resource_id : str
+ ID of the resource to assign.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AssignWebhookResourceResponseDto]
+ Resource assigned to webhook.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources",
+ method="POST",
+ json={
+ "resource_type": resource_type,
+ "resource_id": resource_id,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AssignWebhookResourceResponseDto,
+ parse_obj_as(
+ type_=AssignWebhookResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Any,
+ parse_obj_as(
+ type_=typing.Any, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def remove_webhook_resource(
+ self,
+ webhook_id: str,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[None]:
+ """
+ Detaches a resource from this webhook. Completions of the resource no longer trigger delivery to this webhook.
+
+ The webhook and the resource itself are not deleted.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def list_webhooks_for_resource(
+ self,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ is_active: typing.Optional[bool] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ListWebhooksResponseDto]:
+ """
+ Returns all webhooks currently assigned to the given resource.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ is_active : typing.Optional[bool]
+ Filter by active status. Omit to return webhooks regardless of status.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ListWebhooksResponseDto]
+ Webhooks for resource retrieved successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"catchAll/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}/webhooks",
+ method="GET",
+ params={
+ "is_active": is_active,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhooksResponseDto,
+ parse_obj_as(
+ type_=ListWebhooksResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def get_webhook_delivery_history(
+ self,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[DeliveryHistoryResponseDto]:
+ """
+ Returns a paginated delivery log for a given resource, ordered by timestamp descending.
+
+ Each record shows the webhook dispatched, the HTTP status code returned, delivery outcome, and any error or warning messages. Use this to debug failed deliveries or audit dispatch activity.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+ Type of the resource to retrieve delivery history for.
+
+ resource_id : str
+ Identifier of the resource to retrieve delivery history for.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[DeliveryHistoryResponseDto]
+ Webhook delivery history retrieved successfully.
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "catchAll/webhook-history",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "resource_id": resource_id,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DeliveryHistoryResponseDto,
+ parse_obj_as(
+ type_=DeliveryHistoryResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawWebhooksClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list_webhooks(
+ self,
+ *,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ search: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ListWebhooksResponseDto]:
+ """
+ Returns a paginated list of webhooks belonging to the organization.
+
+ Parameters
+ ----------
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ search : typing.Optional[str]
+ Filter results by text (case-insensitive substring match).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ListWebhooksResponseDto]
+ Webhooks retrieved successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/webhooks",
+ method="GET",
+ params={
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhooksResponseDto,
+ parse_obj_as(
+ type_=ListWebhooksResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def create_webhook(
+ self,
+ *,
+ name: str,
+ url: str,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[CreateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[CreateWebhookResponseDto]:
+ """
+ Creates a new webhook endpoint for the organization.
+
+ Parameters
+ ----------
+ name : str
+ Human-readable label for this webhook.
+
+ url : str
+ Destination URL that receives the payload. Must use HTTPS. IP addresses are not accepted.
+
+ Type-specific URL requirements:
+ - `slack`: Must start with `https://hooks.slack.com/`.
+ - `teams`: Hostname must match `*.webhook.office.com` or `*.webhook.office365.com`.
+ - `generic`: Any valid HTTPS domain.
+ - `custom`: Any valid HTTPS domain.
+
+ When `type` is omitted, it is auto-detected from the URL.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Custom HTTP headers forwarded with each delivery.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Query parameters appended to the webhook URL.
+
+ auth : typing.Optional[CreateWebhookRequestDtoAuth]
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload transformation configuration. Required only when `type` is `custom`.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[CreateWebhookResponseDto]
+ Webhook created successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/webhooks",
+ method="POST",
+ json={
+ "name": name,
+ "url": url,
+ "type": type,
+ "delivery_mode": delivery_mode,
+ "method": method,
+ "headers": headers,
+ "params": params,
+ "auth": convert_and_respect_annotation_metadata(
+ object_=auth, annotation=CreateWebhookRequestDtoAuth, direction="write"
+ ),
+ "formatter_config": formatter_config,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CreateWebhookResponseDto,
+ parse_obj_as(
+ type_=CreateWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def get_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[GetWebhookResponseDto]:
+ """
+ Returns the full configuration of a single webhook by ID.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[GetWebhookResponseDto]
+ Webhook retrieved successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ GetWebhookResponseDto,
+ parse_obj_as(
+ type_=GetWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def delete_webhook(
+ self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[None]:
+ """
+ Permanently deletes a webhook and removes all resource assignments.
+
+ Assigned jobs and monitors no longer trigger delivery to this webhook. This operation cannot be undone.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def update_webhook(
+ self,
+ webhook_id: str,
+ *,
+ name: typing.Optional[str] = OMIT,
+ url: typing.Optional[str] = OMIT,
+ type: typing.Optional[WebhookType] = OMIT,
+ delivery_mode: typing.Optional[DeliveryMode] = OMIT,
+ method: typing.Optional[HttpMethod] = OMIT,
+ headers: typing.Optional[typing.Dict[str, str]] = OMIT,
+ params: typing.Optional[typing.Dict[str, str]] = OMIT,
+ auth: typing.Optional[UpdateWebhookRequestDtoAuth] = OMIT,
+ formatter_config: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ is_active: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[UpdateWebhookResponseDto]:
+ """
+ Updates one or more fields of an existing webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ name : typing.Optional[str]
+ Updated webhook name.
+
+ url : typing.Optional[str]
+ Updated destination URL. Must use HTTPS. Type-specific URL rules apply.
+
+ type : typing.Optional[WebhookType]
+
+ delivery_mode : typing.Optional[DeliveryMode]
+
+ method : typing.Optional[HttpMethod]
+
+ headers : typing.Optional[typing.Dict[str, str]]
+ Updated HTTP headers. Replaces existing headers entirely.
+
+ params : typing.Optional[typing.Dict[str, str]]
+ Updated query parameters. Replaces existing params entirely.
+
+ auth : typing.Optional[UpdateWebhookRequestDtoAuth]
+ Updated authentication configuration. Replaces existing auth entirely.
+
+ formatter_config : typing.Optional[typing.Dict[str, typing.Any]]
+ Updated formatter configuration.
+
+ is_active : typing.Optional[bool]
+ Set to `false` to disable delivery without deleting the webhook.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[UpdateWebhookResponseDto]
+ Webhook updated successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}",
+ method="PATCH",
+ json={
+ "name": name,
+ "url": url,
+ "type": type,
+ "delivery_mode": delivery_mode,
+ "method": method,
+ "headers": headers,
+ "params": params,
+ "auth": convert_and_respect_annotation_metadata(
+ object_=auth, annotation=UpdateWebhookRequestDtoAuth, direction="write"
+ ),
+ "formatter_config": formatter_config,
+ "is_active": is_active,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UpdateWebhookResponseDto,
+ parse_obj_as(
+ type_=UpdateWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def test_webhook(
+ self,
+ webhook_id: str,
+ *,
+ payload: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[TestWebhookResponseDto]:
+ """
+ Sends a test HTTP request to the webhook URL using the webhook's configured method, headers, and auth. Returns the response from the target endpoint.
+
+ Use this to verify URL reachability and authentication before attaching the webhook to a live job or monitor.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ payload : typing.Optional[typing.Dict[str, typing.Any]]
+ Custom payload to send in the test request. If omitted, a synthetic
+ test payload is sent.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[TestWebhookResponseDto]
+ Test delivery attempted. Check `success` and `http_status_code` for the outcome.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/test",
+ method="POST",
+ json={
+ "payload": payload,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ TestWebhookResponseDto,
+ parse_obj_as(
+ type_=TestWebhookResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def list_webhook_resources(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: typing.Optional[MappableResourceType] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ListWebhookResourcesResponseDto]:
+ """
+ Returns a paginated list of resources currently assigned to this webhook.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : typing.Optional[MappableResourceType]
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of assignments per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ListWebhookResourcesResponseDto]
+ Webhook resource assignments retrieved successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhookResourcesResponseDto,
+ parse_obj_as(
+ type_=ListWebhookResourcesResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def assign_webhook_resource(
+ self,
+ webhook_id: str,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[AssignWebhookResourceResponseDto]:
+ """
+ Attaches a job, monitor, or monitor group to the webhook. When the
+ resource completes, the webhook receives a delivery.
+
+ A single webhook can be assigned to multiple resources. Each resource
+ can have up to 5 webhooks assigned.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+ Type of resource to assign.
+
+ resource_id : str
+ ID of the resource to assign.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AssignWebhookResourceResponseDto]
+ Resource assigned to webhook.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources",
+ method="POST",
+ json={
+ "resource_type": resource_type,
+ "resource_id": resource_id,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AssignWebhookResourceResponseDto,
+ parse_obj_as(
+ type_=AssignWebhookResourceResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Any,
+ parse_obj_as(
+ type_=typing.Any, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def remove_webhook_resource(
+ self,
+ webhook_id: str,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[None]:
+ """
+ Detaches a resource from this webhook. Completions of the resource no longer trigger delivery to this webhook.
+
+ The webhook and the resource itself are not deleted.
+
+ Parameters
+ ----------
+ webhook_id : str
+ Unique webhook identifier.
+
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/webhooks/{encode_path_param(webhook_id)}/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def list_webhooks_for_resource(
+ self,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ *,
+ is_active: typing.Optional[bool] = None,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ListWebhooksResponseDto]:
+ """
+ Returns all webhooks currently assigned to the given resource.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+
+ resource_id : str
+ Unique resource identifier.
+
+ is_active : typing.Optional[bool]
+ Filter by active status. Omit to return webhooks regardless of status.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of webhooks per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ListWebhooksResponseDto]
+ Webhooks for resource retrieved successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"catchAll/resources/{encode_path_param(resource_type)}/{encode_path_param(resource_id)}/webhooks",
+ method="GET",
+ params={
+ "is_active": is_active,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ListWebhooksResponseDto,
+ parse_obj_as(
+ type_=ListWebhooksResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def get_webhook_delivery_history(
+ self,
+ *,
+ resource_type: MappableResourceType,
+ resource_id: str,
+ page: typing.Optional[int] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[DeliveryHistoryResponseDto]:
+ """
+ Returns a paginated delivery log for a given resource, ordered by timestamp descending.
+
+ Each record shows the webhook dispatched, the HTTP status code returned, delivery outcome, and any error or warning messages. Use this to debug failed deliveries or audit dispatch activity.
+
+ Parameters
+ ----------
+ resource_type : MappableResourceType
+ Type of the resource to retrieve delivery history for.
+
+ resource_id : str
+ Identifier of the resource to retrieve delivery history for.
+
+ page : typing.Optional[int]
+ Page number to retrieve.
+
+ page_size : typing.Optional[int]
+ Number of records per page.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[DeliveryHistoryResponseDto]
+ Webhook delivery history retrieved successfully.
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "catchAll/webhook-history",
+ method="GET",
+ params={
+ "resource_type": resource_type,
+ "resource_id": resource_id,
+ "page": page,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DeliveryHistoryResponseDto,
+ parse_obj_as(
+ type_=DeliveryHistoryResponseDto, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ValidationErrorResponse,
+ parse_obj_as(
+ type_=ValidationErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/newscatcher_catchall/webhooks/types/__init__.py b/src/newscatcher_catchall/webhooks/types/__init__.py
new file mode 100644
index 0000000..12258a2
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/types/__init__.py
@@ -0,0 +1,63 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .create_webhook_request_dto_auth import (
+ CreateWebhookRequestDtoAuth,
+ CreateWebhookRequestDtoAuth_ApiKey,
+ CreateWebhookRequestDtoAuth_Basic,
+ CreateWebhookRequestDtoAuth_Bearer,
+ )
+ from .update_webhook_request_dto_auth import (
+ UpdateWebhookRequestDtoAuth,
+ UpdateWebhookRequestDtoAuth_ApiKey,
+ UpdateWebhookRequestDtoAuth_Basic,
+ UpdateWebhookRequestDtoAuth_Bearer,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "CreateWebhookRequestDtoAuth": ".create_webhook_request_dto_auth",
+ "CreateWebhookRequestDtoAuth_ApiKey": ".create_webhook_request_dto_auth",
+ "CreateWebhookRequestDtoAuth_Basic": ".create_webhook_request_dto_auth",
+ "CreateWebhookRequestDtoAuth_Bearer": ".create_webhook_request_dto_auth",
+ "UpdateWebhookRequestDtoAuth": ".update_webhook_request_dto_auth",
+ "UpdateWebhookRequestDtoAuth_ApiKey": ".update_webhook_request_dto_auth",
+ "UpdateWebhookRequestDtoAuth_Basic": ".update_webhook_request_dto_auth",
+ "UpdateWebhookRequestDtoAuth_Bearer": ".update_webhook_request_dto_auth",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "CreateWebhookRequestDtoAuth",
+ "CreateWebhookRequestDtoAuth_ApiKey",
+ "CreateWebhookRequestDtoAuth_Basic",
+ "CreateWebhookRequestDtoAuth_Bearer",
+ "UpdateWebhookRequestDtoAuth",
+ "UpdateWebhookRequestDtoAuth_ApiKey",
+ "UpdateWebhookRequestDtoAuth_Basic",
+ "UpdateWebhookRequestDtoAuth_Bearer",
+]
diff --git a/src/newscatcher_catchall/webhooks/types/create_webhook_request_dto_auth.py b/src/newscatcher_catchall/webhooks/types/create_webhook_request_dto_auth.py
new file mode 100644
index 0000000..9539fa2
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/types/create_webhook_request_dto_auth.py
@@ -0,0 +1,82 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from __future__ import annotations
+
+import typing
+
+import pydantic
+import typing_extensions
+from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class CreateWebhookRequestDtoAuth_Bearer(UniversalBaseModel):
+ """
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+ """
+
+ type: typing.Literal["bearer"] = "bearer"
+ token: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+class CreateWebhookRequestDtoAuth_ApiKey(UniversalBaseModel):
+ """
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+ """
+
+ type: typing.Literal["api_key"] = "api_key"
+ header: str
+ value: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+class CreateWebhookRequestDtoAuth_Basic(UniversalBaseModel):
+ """
+ Authentication forwarded with each delivery. Supported types:
+ - `bearer`: Adds an `Authorization: Bearer ` header.
+ - `api_key`: Adds a custom header with the specified name and value.
+ - `basic`: Adds an `Authorization: Basic ` header.
+ """
+
+ type: typing.Literal["basic"] = "basic"
+ username: str
+ password: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+CreateWebhookRequestDtoAuth = typing_extensions.Annotated[
+ typing.Union[
+ CreateWebhookRequestDtoAuth_Bearer, CreateWebhookRequestDtoAuth_ApiKey, CreateWebhookRequestDtoAuth_Basic
+ ],
+ pydantic.Field(discriminator="type"),
+]
diff --git a/src/newscatcher_catchall/webhooks/types/update_webhook_request_dto_auth.py b/src/newscatcher_catchall/webhooks/types/update_webhook_request_dto_auth.py
new file mode 100644
index 0000000..e1f851e
--- /dev/null
+++ b/src/newscatcher_catchall/webhooks/types/update_webhook_request_dto_auth.py
@@ -0,0 +1,73 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from __future__ import annotations
+
+import typing
+
+import pydantic
+import typing_extensions
+from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class UpdateWebhookRequestDtoAuth_Bearer(UniversalBaseModel):
+ """
+ Updated authentication configuration. Replaces existing auth entirely.
+ """
+
+ type: typing.Literal["bearer"] = "bearer"
+ token: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+class UpdateWebhookRequestDtoAuth_ApiKey(UniversalBaseModel):
+ """
+ Updated authentication configuration. Replaces existing auth entirely.
+ """
+
+ type: typing.Literal["api_key"] = "api_key"
+ header: str
+ value: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+class UpdateWebhookRequestDtoAuth_Basic(UniversalBaseModel):
+ """
+ Updated authentication configuration. Replaces existing auth entirely.
+ """
+
+ type: typing.Literal["basic"] = "basic"
+ username: str
+ password: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
+
+
+UpdateWebhookRequestDtoAuth = typing_extensions.Annotated[
+ typing.Union[
+ UpdateWebhookRequestDtoAuth_Bearer, UpdateWebhookRequestDtoAuth_ApiKey, UpdateWebhookRequestDtoAuth_Basic
+ ],
+ pydantic.Field(discriminator="type"),
+]