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"), +]