diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7248fd7c..5ea724d9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,7 +18,7 @@ jobs:
lint:
timeout-minutes: 10
name: lint
- runs-on: ${{ github.repository == 'stainless-sdks/onlyfansapi-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -41,7 +41,7 @@ jobs:
permissions:
contents: read
id-token: write
- runs-on: ${{ github.repository == 'stainless-sdks/onlyfansapi-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -78,7 +78,7 @@ jobs:
test:
timeout-minutes: 10
name: test
- runs-on: ${{ github.repository == 'stainless-sdks/onlyfansapi-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index cda9cbdf..10f30916 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.2"
+ ".": "0.2.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 6127ab43..0751bec3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 266
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/onlyfansapi/onlyfansapi-ba5efdf86108ef077f2db1f8a05b84d58f7f218fe2b7e0eb72e3c371cfa30015.yml
-openapi_spec_hash: 6c2d47cd85674ece07dc37e471a36ac9
+configured_endpoints: 265
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/onlyfansapi/onlyfansapi-5ac36f138ceb953477f1830fb90a8455ee5fb60bb00b79351f49a0d930a7bb44.yml
+openapi_spec_hash: 4925a6c29f19d5958094e6a45fb3cd5a
config_hash: 397c91e15c0024f8b5bbed9b82c2348c
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9d2a81d..c3a89683 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,262 @@
# Changelog
+## 0.2.0 (2026-08-26)
+
+Full Changelog: [v0.1.2...v0.2.0](https://github.com/onlyfansapi/onlyfansapi-python/compare/v0.1.2...v0.2.0)
+
+### Features
+
+* **api:** api update ([7473071](https://github.com/onlyfansapi/onlyfansapi-python/commit/74730714f173cf850e0eb7975f03eec04f9dc8cc))
+* **api:** api update ([6ce56b0](https://github.com/onlyfansapi/onlyfansapi-python/commit/6ce56b042902c60d0265a3b28c5100c27f51d566))
+* **api:** api update ([f0ae816](https://github.com/onlyfansapi/onlyfansapi-python/commit/f0ae8161addd075897099da7a4f6952cd9f7c538))
+* **api:** api update ([b8ee283](https://github.com/onlyfansapi/onlyfansapi-python/commit/b8ee283efe94a9bc2338d29b93fd1c0efda4166e))
+* **api:** api update ([78fc5ee](https://github.com/onlyfansapi/onlyfansapi-python/commit/78fc5ee8b96e4b6f879459f02af92a0328bf6ffa))
+* **api:** api update ([253811c](https://github.com/onlyfansapi/onlyfansapi-python/commit/253811ccddb3642133030b0398247f7e153830a0))
+* **api:** api update ([a8ad518](https://github.com/onlyfansapi/onlyfansapi-python/commit/a8ad51825b5fb756c8bdf68944ae66da6f4c3eb0))
+* **api:** api update ([89c4de4](https://github.com/onlyfansapi/onlyfansapi-python/commit/89c4de4ba7fb9a789dfb8a0e01cbe61b16c8701d))
+* **api:** api update ([d0e5322](https://github.com/onlyfansapi/onlyfansapi-python/commit/d0e53221eecfb493a4607194bf28a81f9b372a43))
+* **api:** api update ([0cc4697](https://github.com/onlyfansapi/onlyfansapi-python/commit/0cc46970e4bb4a1e947737b47d177ce67ef99579))
+* **api:** api update ([c7bed45](https://github.com/onlyfansapi/onlyfansapi-python/commit/c7bed4511bd2fa1c394cd1076fbd1430e34477c6))
+* **api:** api update ([d41110b](https://github.com/onlyfansapi/onlyfansapi-python/commit/d41110bfe79b27ab9b14acc56479dd3e1828c3fb))
+* **api:** api update ([930eecf](https://github.com/onlyfansapi/onlyfansapi-python/commit/930eecf179c3c1ec246f7308901ebb44ad4529d4))
+* **api:** api update ([5eaf7b8](https://github.com/onlyfansapi/onlyfansapi-python/commit/5eaf7b862cd58198b4d370c588e1b4e06517dcbb))
+* **api:** api update ([ed392bf](https://github.com/onlyfansapi/onlyfansapi-python/commit/ed392bf29df7ce14f69760ea55338a61aaf1b8a7))
+* **api:** api update ([8d7342b](https://github.com/onlyfansapi/onlyfansapi-python/commit/8d7342b6d4076c2087a926f7f79b776036826b85))
+* **api:** api update ([96bef37](https://github.com/onlyfansapi/onlyfansapi-python/commit/96bef37d1dafec25f6edaa283b070041a567ab46))
+* **api:** api update ([b073e8f](https://github.com/onlyfansapi/onlyfansapi-python/commit/b073e8f89f72d1960c9250a5b4b898401ba68216))
+* **api:** api update ([e222ff8](https://github.com/onlyfansapi/onlyfansapi-python/commit/e222ff85f12c5818c112fa577d63d7199fc30277))
+* **api:** api update ([6df6e2a](https://github.com/onlyfansapi/onlyfansapi-python/commit/6df6e2af35b416e3dfdee775b65ebbaff3d6a9fc))
+* **api:** api update ([a2ac1bd](https://github.com/onlyfansapi/onlyfansapi-python/commit/a2ac1bd2100e6fe643ae2db04a789c250ba00d65))
+* **api:** api update ([4bbfdd1](https://github.com/onlyfansapi/onlyfansapi-python/commit/4bbfdd189f41fe370f35ec1b9e428a3b1e5699fd))
+* **api:** api update ([2ad0d5f](https://github.com/onlyfansapi/onlyfansapi-python/commit/2ad0d5fc46416573dc8cf8836744636c8586120c))
+* **api:** api update ([04e8626](https://github.com/onlyfansapi/onlyfansapi-python/commit/04e862686e19e33646a6e096dea76e21a5cd6f27))
+* **api:** api update ([db2c99c](https://github.com/onlyfansapi/onlyfansapi-python/commit/db2c99c027f12690ef751eeed5c1b8fe2ae7e23c))
+* **api:** api update ([a0e30d7](https://github.com/onlyfansapi/onlyfansapi-python/commit/a0e30d74e9c7245d836c3cdb9d53c7e666ec5442))
+* **api:** api update ([1a8acd1](https://github.com/onlyfansapi/onlyfansapi-python/commit/1a8acd18cce3fe2d56e8c8da5d24bca8741703fa))
+* **api:** api update ([5f775d7](https://github.com/onlyfansapi/onlyfansapi-python/commit/5f775d77cbc18ce51badea04ef40f442f76da7e7))
+* **api:** api update ([28864ee](https://github.com/onlyfansapi/onlyfansapi-python/commit/28864eea9911a6c0ce9d011cc97f14cab53416ac))
+* **api:** api update ([3ed6a88](https://github.com/onlyfansapi/onlyfansapi-python/commit/3ed6a88a772874e34820aed36250aa8c92a2094c))
+* **api:** api update ([6109204](https://github.com/onlyfansapi/onlyfansapi-python/commit/61092043eacd145962a8b12c14cee3ffbff585b4))
+* **api:** api update ([cfcce74](https://github.com/onlyfansapi/onlyfansapi-python/commit/cfcce7497265a62f22a13e68b3371132b17eab76))
+* **api:** api update ([ec9c9b7](https://github.com/onlyfansapi/onlyfansapi-python/commit/ec9c9b704bf4f657c5a7bd84a4d5a4e5cdd47595))
+* **api:** api update ([727a00c](https://github.com/onlyfansapi/onlyfansapi-python/commit/727a00cc6b7f36c1bcf10a7647b4d3aa93cce93b))
+* **api:** api update ([9889722](https://github.com/onlyfansapi/onlyfansapi-python/commit/9889722219f443635f4a43ecfd85c3c00e9828ef))
+* **api:** api update ([e6ea88d](https://github.com/onlyfansapi/onlyfansapi-python/commit/e6ea88d737ec6b39d7d6a44a1cab409fc28acb7f))
+* **api:** api update ([023b1fc](https://github.com/onlyfansapi/onlyfansapi-python/commit/023b1fc3c73a5831955df00bece191c9e6d0c9a6))
+* **api:** api update ([fa0b6cb](https://github.com/onlyfansapi/onlyfansapi-python/commit/fa0b6cbfbdfc703734db97b2696d672e5e9623ca))
+* **api:** api update ([5827381](https://github.com/onlyfansapi/onlyfansapi-python/commit/582738189c9ac1a15291974eadcdab3cf142097c))
+* **api:** api update ([32c6f88](https://github.com/onlyfansapi/onlyfansapi-python/commit/32c6f88e69572a26f95de0a553786bff41dc6dc2))
+* **api:** api update ([95218c9](https://github.com/onlyfansapi/onlyfansapi-python/commit/95218c90954a7f89c429153e2e39a74edae409ab))
+* **api:** api update ([ed4c419](https://github.com/onlyfansapi/onlyfansapi-python/commit/ed4c419b5d56cddcc27679ff2158f58d3e827cb4))
+* **api:** api update ([9193673](https://github.com/onlyfansapi/onlyfansapi-python/commit/9193673f40a967a7c979465fd0b691a4b1e59bc8))
+* **api:** api update ([58a4812](https://github.com/onlyfansapi/onlyfansapi-python/commit/58a4812b204afbd08b301063b4f34613cacc836f))
+* **api:** api update ([3d3c32a](https://github.com/onlyfansapi/onlyfansapi-python/commit/3d3c32a37b1f8326e4ffff6ccd0c105de24bad18))
+* **api:** api update ([5fea6cc](https://github.com/onlyfansapi/onlyfansapi-python/commit/5fea6cca3d9a706df74b61e9e734d35382def2e4))
+* **api:** api update ([5a1cd93](https://github.com/onlyfansapi/onlyfansapi-python/commit/5a1cd93679d57d6f7931de339b21bfaaa5fd144e))
+* **api:** api update ([60d3eac](https://github.com/onlyfansapi/onlyfansapi-python/commit/60d3eac8991bd7cec36ecb3f99f7984e6d333212))
+* **api:** api update ([9b58972](https://github.com/onlyfansapi/onlyfansapi-python/commit/9b58972a7e11f356300d950591b739f3db725b0c))
+* **api:** api update ([3d4e82a](https://github.com/onlyfansapi/onlyfansapi-python/commit/3d4e82a74cd17580af41d4692c5eb252c4901be4))
+* **api:** api update ([ee28e92](https://github.com/onlyfansapi/onlyfansapi-python/commit/ee28e926834d57e16d1de4ed6c95a533d5672c02))
+* **api:** api update ([bc13cfa](https://github.com/onlyfansapi/onlyfansapi-python/commit/bc13cfa62a0ba7eab9a1bddc4d3cae039ba7b520))
+* **api:** api update ([91252ee](https://github.com/onlyfansapi/onlyfansapi-python/commit/91252eef3de9b5add88105c123ba34e59790164d))
+* **api:** api update ([4ecc6fe](https://github.com/onlyfansapi/onlyfansapi-python/commit/4ecc6fea51ce942e0b3c87b06f7000b26020fdfc))
+* **api:** api update ([8137610](https://github.com/onlyfansapi/onlyfansapi-python/commit/81376103c50a835a8aa6e5b4430c594f87168b86))
+* **api:** api update ([81f42ff](https://github.com/onlyfansapi/onlyfansapi-python/commit/81f42ffb06fa8bffcec38c37e281f0fce5767563))
+* **api:** api update ([98d06fa](https://github.com/onlyfansapi/onlyfansapi-python/commit/98d06fae448d4f214bd3ebfe44df6c62825c4655))
+* **api:** api update ([8017401](https://github.com/onlyfansapi/onlyfansapi-python/commit/80174010ca5107a6b01499c7bcd9267f9a750793))
+* **api:** api update ([2f12252](https://github.com/onlyfansapi/onlyfansapi-python/commit/2f122524efdf42653d50d895ff8921c37aaedcf7))
+* **api:** api update ([59e47be](https://github.com/onlyfansapi/onlyfansapi-python/commit/59e47be2ce117f2eab9ee823ac8de52a1396eb8e))
+* **api:** api update ([c4b4cbc](https://github.com/onlyfansapi/onlyfansapi-python/commit/c4b4cbc1ebdaaa58f29fc66e6adb94d9bcfbca33))
+* **api:** api update ([a3f3602](https://github.com/onlyfansapi/onlyfansapi-python/commit/a3f36027879b1fedba7b20d6a5a6b13582792ab0))
+* **api:** api update ([3dbd253](https://github.com/onlyfansapi/onlyfansapi-python/commit/3dbd253b28d5fb6e8adb7022b28bc787d1eb73dd))
+* **api:** api update ([39faabe](https://github.com/onlyfansapi/onlyfansapi-python/commit/39faabeffb6af7053738be1dad15eea1df0f20e2))
+* **api:** api update ([8bd5d84](https://github.com/onlyfansapi/onlyfansapi-python/commit/8bd5d84832181057ef296a044ae4903b7a5017fb))
+* **api:** api update ([3697190](https://github.com/onlyfansapi/onlyfansapi-python/commit/3697190051b6031f79d0e309402dbba8d7261eff))
+* **api:** api update ([f0d6930](https://github.com/onlyfansapi/onlyfansapi-python/commit/f0d6930cdb58e913f6bf366d4b0efc320178eceb))
+* **api:** api update ([1f4ac02](https://github.com/onlyfansapi/onlyfansapi-python/commit/1f4ac02a5623e3f65252680e171e052a951ce441))
+* **api:** api update ([1c39ee2](https://github.com/onlyfansapi/onlyfansapi-python/commit/1c39ee2c56a02ab2c917032244427b5d5c90969d))
+* **api:** api update ([977d8f3](https://github.com/onlyfansapi/onlyfansapi-python/commit/977d8f37d552e87d6566fe75c6b15695242891d3))
+* **api:** api update ([727b77d](https://github.com/onlyfansapi/onlyfansapi-python/commit/727b77d68de20f5ae4ef2a86336e56858fd2b561))
+* **api:** api update ([2028874](https://github.com/onlyfansapi/onlyfansapi-python/commit/20288744b129ce287fd92c3ce3d37f8a3cf8b887))
+* **api:** api update ([cb6a8a3](https://github.com/onlyfansapi/onlyfansapi-python/commit/cb6a8a3b99a7803e71fe81c4775d7bc08c75fe8d))
+* **api:** api update ([a2e9fba](https://github.com/onlyfansapi/onlyfansapi-python/commit/a2e9fba0d16cfb60cdbc7e98f94adc6dc7f20597))
+* **api:** api update ([b67d110](https://github.com/onlyfansapi/onlyfansapi-python/commit/b67d110c34f72e85c8d46044f8b7881a2b0f68ed))
+* **api:** api update ([7a37525](https://github.com/onlyfansapi/onlyfansapi-python/commit/7a375259bfb4e8c7ddd50f4ae8438a2ce25c84cc))
+* **api:** api update ([de02374](https://github.com/onlyfansapi/onlyfansapi-python/commit/de023746aee85ea5bacb3dfb45ee8a22de126653))
+* **api:** api update ([80626d6](https://github.com/onlyfansapi/onlyfansapi-python/commit/80626d6f45a33b16ffee77cd7ebb2115d7197597))
+* **api:** api update ([3b05be2](https://github.com/onlyfansapi/onlyfansapi-python/commit/3b05be2dac74b6886d1447195c16d57a17b1fd23))
+* **api:** api update ([b30430b](https://github.com/onlyfansapi/onlyfansapi-python/commit/b30430bb4db869895bbda74477161206770ef8a2))
+* **api:** api update ([6ce0c66](https://github.com/onlyfansapi/onlyfansapi-python/commit/6ce0c667ef53ccc999e37393debb98a164e9f5a5))
+* **api:** api update ([4f519c6](https://github.com/onlyfansapi/onlyfansapi-python/commit/4f519c6af12b155ab55bc8908e36d76cee693974))
+* **api:** api update ([b68745a](https://github.com/onlyfansapi/onlyfansapi-python/commit/b68745a107dd77c04aa3668a318774b80a840cb3))
+* **api:** api update ([4c4cfa1](https://github.com/onlyfansapi/onlyfansapi-python/commit/4c4cfa16785df1fbc4cb3728406f97a98b7c8161))
+* **api:** api update ([2465884](https://github.com/onlyfansapi/onlyfansapi-python/commit/2465884b3bc9bc3474e496fc13e3585c2c42a7f6))
+* **api:** api update ([bbcf21d](https://github.com/onlyfansapi/onlyfansapi-python/commit/bbcf21dddce7793a49c619dfb4d0dbcddee3d932))
+* **api:** api update ([02527aa](https://github.com/onlyfansapi/onlyfansapi-python/commit/02527aa87aeb05514a9965075390b64cb66c09fb))
+* **api:** api update ([71db779](https://github.com/onlyfansapi/onlyfansapi-python/commit/71db779cabb357927c8f79cb8f0fcd9692b30ae0))
+* **api:** api update ([4edd93f](https://github.com/onlyfansapi/onlyfansapi-python/commit/4edd93fc9ed9cb388ee23920b6b5f570085bc44d))
+* **api:** api update ([4c4fbee](https://github.com/onlyfansapi/onlyfansapi-python/commit/4c4fbee0a34e3947c61c0b7eb6ba81fb71ea7dd8))
+* **api:** api update ([5f83d8e](https://github.com/onlyfansapi/onlyfansapi-python/commit/5f83d8e1d7a63140fa2f334ce8787cc296b3b8c8))
+* **api:** api update ([ff35699](https://github.com/onlyfansapi/onlyfansapi-python/commit/ff35699b05b1968f622c39e5acd873bb3bc7448f))
+* **api:** api update ([53307f5](https://github.com/onlyfansapi/onlyfansapi-python/commit/53307f5b33c42961dbf9f7789352398b1aad35d0))
+* **api:** api update ([1b7e3b7](https://github.com/onlyfansapi/onlyfansapi-python/commit/1b7e3b7d85306ebb0c36b33dc219486c290a07a0))
+* **api:** api update ([870ce5c](https://github.com/onlyfansapi/onlyfansapi-python/commit/870ce5c5344eac82f50ab138e3cf660d5dbcde99))
+* **api:** api update ([4c8f998](https://github.com/onlyfansapi/onlyfansapi-python/commit/4c8f9989a83e200bfda79edba3b644e7bc776734))
+* **api:** api update ([bf85410](https://github.com/onlyfansapi/onlyfansapi-python/commit/bf8541014f378eb7783b4d548dec868ac023fb4b))
+* **api:** api update ([bc4ad9c](https://github.com/onlyfansapi/onlyfansapi-python/commit/bc4ad9cda2cddd4b44f3a6ec598cd9843ff5422e))
+* **api:** api update ([6d845ea](https://github.com/onlyfansapi/onlyfansapi-python/commit/6d845eace2c48224721825fb92f286f41608a531))
+* **api:** api update ([d2ff421](https://github.com/onlyfansapi/onlyfansapi-python/commit/d2ff421e1e4741943cb6dfb61ee8bc68e5273ce7))
+* **api:** api update ([1e34cdf](https://github.com/onlyfansapi/onlyfansapi-python/commit/1e34cdfb2c77dcf8e7bfe3429b624ba6564c12c2))
+* **api:** api update ([02ae244](https://github.com/onlyfansapi/onlyfansapi-python/commit/02ae244cb2aaf005d9244be1cb2410935f626c56))
+* **api:** api update ([179a592](https://github.com/onlyfansapi/onlyfansapi-python/commit/179a5923e7580bf0483d05abccd2ab731a09bc01))
+* **api:** api update ([c7f90dd](https://github.com/onlyfansapi/onlyfansapi-python/commit/c7f90dd1b7064ad48334a1c97791bac616228a25))
+* **api:** api update ([293346c](https://github.com/onlyfansapi/onlyfansapi-python/commit/293346ce4cc45bc6c893ce146907aecd9d45083b))
+* **api:** api update ([9a82aec](https://github.com/onlyfansapi/onlyfansapi-python/commit/9a82aec51c4f60f11ea2d3db069898301c22e48d))
+* **api:** api update ([0742c6b](https://github.com/onlyfansapi/onlyfansapi-python/commit/0742c6b01b8ee727616da3c71232bdb71dc28a7d))
+* **api:** api update ([f557b21](https://github.com/onlyfansapi/onlyfansapi-python/commit/f557b2178e60a8d96edbabe78099094198240c1c))
+* **api:** api update ([c29e6e2](https://github.com/onlyfansapi/onlyfansapi-python/commit/c29e6e299fcae1882ba3a1982ad8996a0e29aa24))
+* **api:** api update ([64e0325](https://github.com/onlyfansapi/onlyfansapi-python/commit/64e03259d17d1f27f44ae4ab2d8ee3cba744677b))
+* **api:** api update ([d69001b](https://github.com/onlyfansapi/onlyfansapi-python/commit/d69001b11519fca2f88a08610e4c11f462b10690))
+* **api:** api update ([f3f6a7d](https://github.com/onlyfansapi/onlyfansapi-python/commit/f3f6a7de15830eabbd9ad57d5edd600a444872cb))
+* **api:** api update ([2e11f3f](https://github.com/onlyfansapi/onlyfansapi-python/commit/2e11f3feabcda807f76fedc5ac8ad70db68ab4d0))
+* **api:** api update ([7d8523a](https://github.com/onlyfansapi/onlyfansapi-python/commit/7d8523acbc7171c2bf2af963f457f242d86e5119))
+* **api:** api update ([3101371](https://github.com/onlyfansapi/onlyfansapi-python/commit/310137122207eeb85389095d4d26dc2555333c2e))
+* **api:** api update ([7c99e2a](https://github.com/onlyfansapi/onlyfansapi-python/commit/7c99e2a1cc79d09a7d53d4c68237af06e4e4d1ab))
+* **api:** api update ([c11f180](https://github.com/onlyfansapi/onlyfansapi-python/commit/c11f180fe2c833e9ad40434312cfe47447be8dfb))
+* **api:** api update ([4830edd](https://github.com/onlyfansapi/onlyfansapi-python/commit/4830eddc35ed953f5730edf979b5c0db75ccb082))
+* **api:** api update ([3ef2bad](https://github.com/onlyfansapi/onlyfansapi-python/commit/3ef2bad1be2bb4fcef4f65dde2d5704384a821c3))
+* **api:** api update ([c4b4d34](https://github.com/onlyfansapi/onlyfansapi-python/commit/c4b4d347ddc13bf7ef358f1953a145aef07c6785))
+* **api:** api update ([6fd0c37](https://github.com/onlyfansapi/onlyfansapi-python/commit/6fd0c3711c712c47f78cae2359ee20eca694e26f))
+* **api:** api update ([84ef257](https://github.com/onlyfansapi/onlyfansapi-python/commit/84ef257f42d7c15262dc63d5869e9b48b8f1d62b))
+* **api:** api update ([a822c22](https://github.com/onlyfansapi/onlyfansapi-python/commit/a822c221e7d433bf7f36f2f608ec6ee2f4212fff))
+* **api:** api update ([96068ce](https://github.com/onlyfansapi/onlyfansapi-python/commit/96068ce6fe8c0fa94b475877815cc8c1670a48b3))
+* **api:** api update ([14e5452](https://github.com/onlyfansapi/onlyfansapi-python/commit/14e54524baf40026eae7cad18828f9e9a9246522))
+* **api:** api update ([9ff85c9](https://github.com/onlyfansapi/onlyfansapi-python/commit/9ff85c92011773ac85fd43a9c8fed24f1d09ed69))
+* **api:** api update ([690697f](https://github.com/onlyfansapi/onlyfansapi-python/commit/690697fed189cd6acc18c9bf40164729e13d5344))
+* **api:** api update ([d4ea3a3](https://github.com/onlyfansapi/onlyfansapi-python/commit/d4ea3a356bab292a092a599f4a4fd7394ae149e1))
+* **api:** api update ([ece2e64](https://github.com/onlyfansapi/onlyfansapi-python/commit/ece2e64dec3f9356b351d1862a1f22871a528970))
+* **api:** api update ([0e5181b](https://github.com/onlyfansapi/onlyfansapi-python/commit/0e5181b69361214e8a78e5ca7c3f915b2ea57aec))
+* **api:** api update ([a2f1e64](https://github.com/onlyfansapi/onlyfansapi-python/commit/a2f1e64f365be407a6b3b5267e293f808fa684e1))
+* **api:** api update ([3093ab5](https://github.com/onlyfansapi/onlyfansapi-python/commit/3093ab5168081988522eaae6afc8aab54e525b0c))
+* **api:** api update ([7d8cf8d](https://github.com/onlyfansapi/onlyfansapi-python/commit/7d8cf8d441a41fd773f832e787da2a17fe97bb5d))
+* **api:** api update ([f07fda7](https://github.com/onlyfansapi/onlyfansapi-python/commit/f07fda75461b72f717dbea6aecb141f63153afd6))
+* **api:** api update ([65fd101](https://github.com/onlyfansapi/onlyfansapi-python/commit/65fd1014fca65692c9c0d1a9960fafea61a0d876))
+* **api:** api update ([1a4584e](https://github.com/onlyfansapi/onlyfansapi-python/commit/1a4584e4ac241ff185911411b0b56fa2eb73b62c))
+* **api:** api update ([6b0bbf8](https://github.com/onlyfansapi/onlyfansapi-python/commit/6b0bbf8ccd12982f2ff8e53014db7e24dfb2bf83))
+* **api:** api update ([6f86464](https://github.com/onlyfansapi/onlyfansapi-python/commit/6f8646432b9297b31885ea2912f1325ba86e5949))
+* **api:** api update ([d99d328](https://github.com/onlyfansapi/onlyfansapi-python/commit/d99d328ea9231b173ce3694207f1acb04331322c))
+* **api:** api update ([1a1f70d](https://github.com/onlyfansapi/onlyfansapi-python/commit/1a1f70df2843def16fe176ac59863f41b3864467))
+* **api:** api update ([6733605](https://github.com/onlyfansapi/onlyfansapi-python/commit/673360549e2dba4c0558234ee9b172304530f3d8))
+* **api:** api update ([34b0116](https://github.com/onlyfansapi/onlyfansapi-python/commit/34b01164051b22ec5c95c03104ecf086cf5c38a9))
+* **api:** api update ([2623e4f](https://github.com/onlyfansapi/onlyfansapi-python/commit/2623e4ff6f4beb7e4601c4d5bfd3c445be5b53d8))
+* **api:** api update ([5ecfe50](https://github.com/onlyfansapi/onlyfansapi-python/commit/5ecfe507bb879f29f5f7d3ef84294d7495a77c27))
+* **api:** api update ([e04b31f](https://github.com/onlyfansapi/onlyfansapi-python/commit/e04b31fbb676188666fea058aec58892b665e560))
+* **api:** api update ([ff80138](https://github.com/onlyfansapi/onlyfansapi-python/commit/ff8013848469ba5059d0ae9f43164ea3de6f17ec))
+* **api:** api update ([86e264e](https://github.com/onlyfansapi/onlyfansapi-python/commit/86e264e4f4596e989c1227b0f8717a562ccb5c8a))
+* **api:** api update ([7dd3175](https://github.com/onlyfansapi/onlyfansapi-python/commit/7dd3175dea435e9d03ba94cd548b45588cdadc12))
+* **api:** api update ([2eede93](https://github.com/onlyfansapi/onlyfansapi-python/commit/2eede932d7795151755cef1373ef723b594b51ec))
+* **api:** api update ([d7f273e](https://github.com/onlyfansapi/onlyfansapi-python/commit/d7f273e31c9f47d142a18b0a2a9a72b520277a41))
+* **api:** api update ([61824c2](https://github.com/onlyfansapi/onlyfansapi-python/commit/61824c2c6a658abc8a5b256f26153c852fdf07ca))
+* **api:** api update ([c065f5e](https://github.com/onlyfansapi/onlyfansapi-python/commit/c065f5e87e1c8a34984dabc5b36fc8b5d89dc04e))
+* **api:** api update ([e6371a9](https://github.com/onlyfansapi/onlyfansapi-python/commit/e6371a97aef6d5b5724bee5ff93856d5444f39cf))
+* **api:** api update ([fcbc734](https://github.com/onlyfansapi/onlyfansapi-python/commit/fcbc734d81a4fe09530f934f619c65bbbbc21a8c))
+* **api:** api update ([27d82bd](https://github.com/onlyfansapi/onlyfansapi-python/commit/27d82bd7196e95abb0d4dae7b7d83880e9758e2e))
+* **api:** api update ([8e6951a](https://github.com/onlyfansapi/onlyfansapi-python/commit/8e6951a2d77aa5c1e7bf04346006b23aac571f12))
+* **api:** api update ([2a9d43d](https://github.com/onlyfansapi/onlyfansapi-python/commit/2a9d43da2583fc5787269d8419544ba0ed3256f6))
+* **api:** api update ([219a4ad](https://github.com/onlyfansapi/onlyfansapi-python/commit/219a4ad76a013f4409e78c39bf98ff178063b0e5))
+* **api:** api update ([b4de79a](https://github.com/onlyfansapi/onlyfansapi-python/commit/b4de79adfe74b16d971c2ac5c0483c6ea2823b17))
+* **api:** api update ([6dac13e](https://github.com/onlyfansapi/onlyfansapi-python/commit/6dac13ef7bfe10bdf41a445e2bbf733574b6ce49))
+* **api:** api update ([d37311c](https://github.com/onlyfansapi/onlyfansapi-python/commit/d37311c2c3241b721cfb6c4bb23768871ddb37d3))
+* **api:** api update ([ad185f2](https://github.com/onlyfansapi/onlyfansapi-python/commit/ad185f2dba151f99f4305a991d59c732bfed3567))
+* **api:** api update ([fb91a8a](https://github.com/onlyfansapi/onlyfansapi-python/commit/fb91a8a2ae01b12b8e23d04019f14cf589d2b6d6))
+* **api:** api update ([34b2ef5](https://github.com/onlyfansapi/onlyfansapi-python/commit/34b2ef520908d102c015ca22ae14cd962971803a))
+* **api:** api update ([bc6eecc](https://github.com/onlyfansapi/onlyfansapi-python/commit/bc6eecce257a653fb292faa08083275940e2988d))
+* **api:** api update ([8c1fc5b](https://github.com/onlyfansapi/onlyfansapi-python/commit/8c1fc5bf584345d8f7322a364f372bafb9a61105))
+* **api:** api update ([b3e9ad4](https://github.com/onlyfansapi/onlyfansapi-python/commit/b3e9ad4baf8a196ac8709aebd2544c35d7c4cb9f))
+* **api:** api update ([6206d4e](https://github.com/onlyfansapi/onlyfansapi-python/commit/6206d4ea6f90f4670efd1bbbc575198dc83fa378))
+* **api:** api update ([c4cb460](https://github.com/onlyfansapi/onlyfansapi-python/commit/c4cb46035be4dc92c35f839c4b0357c669990ee7))
+* **api:** api update ([5730eb7](https://github.com/onlyfansapi/onlyfansapi-python/commit/5730eb709799c6cb7602376ad4932b99d272fda8))
+* **api:** api update ([05a7a76](https://github.com/onlyfansapi/onlyfansapi-python/commit/05a7a761f83da67c48b5adb881fb7355fe273d90))
+* **api:** api update ([a5bef62](https://github.com/onlyfansapi/onlyfansapi-python/commit/a5bef6249c6f41017cbdf93596d31b1d1d734d8d))
+* **api:** api update ([cd59ef9](https://github.com/onlyfansapi/onlyfansapi-python/commit/cd59ef9dca60b078e1ca0b3735af93d67e3d4151))
+* **api:** api update ([85a1343](https://github.com/onlyfansapi/onlyfansapi-python/commit/85a134346cdbe797c852dea9ea87cb8fb2b6b85f))
+* **api:** api update ([3b888d1](https://github.com/onlyfansapi/onlyfansapi-python/commit/3b888d1755cb600905e1a0517077bf0429b822c6))
+* **api:** api update ([c9bffa9](https://github.com/onlyfansapi/onlyfansapi-python/commit/c9bffa987a47eb406f6525aa2fb409e925d45c3b))
+* **api:** api update ([cd72d9b](https://github.com/onlyfansapi/onlyfansapi-python/commit/cd72d9b088e050776dd050a0aca1222404fd178c))
+* **api:** api update ([98cccb2](https://github.com/onlyfansapi/onlyfansapi-python/commit/98cccb29301a35d2fa083b533b772d834fe0326d))
+* **api:** api update ([5e54e4d](https://github.com/onlyfansapi/onlyfansapi-python/commit/5e54e4dcab360a81947e39d3a917851859db8235))
+* **api:** api update ([c0e6856](https://github.com/onlyfansapi/onlyfansapi-python/commit/c0e6856931fd11a311e8f23773d2d92f011239ff))
+* **api:** api update ([8094519](https://github.com/onlyfansapi/onlyfansapi-python/commit/8094519c54d9931fb860e6b8c7ae002d9ff1317c))
+* **api:** api update ([cc58005](https://github.com/onlyfansapi/onlyfansapi-python/commit/cc58005c7034682c16182a57dddd4810849773a1))
+* **api:** api update ([e79bbd9](https://github.com/onlyfansapi/onlyfansapi-python/commit/e79bbd972288c882a5cbafbf30a99f8b38d77ab6))
+* **api:** api update ([c3e0de4](https://github.com/onlyfansapi/onlyfansapi-python/commit/c3e0de4a6dd1170cd75d77838f07fb395005b452))
+* **api:** api update ([4a0e815](https://github.com/onlyfansapi/onlyfansapi-python/commit/4a0e815fe74f83e0fad633e6fc1033ec0afbcc2a))
+* **api:** api update ([22e3621](https://github.com/onlyfansapi/onlyfansapi-python/commit/22e362138fea30764aff89a049bc5ab8acd163d9))
+* **api:** api update ([b9bc8ef](https://github.com/onlyfansapi/onlyfansapi-python/commit/b9bc8ef90c9c5cfbd5b81add12e94e78786b46b0))
+* **api:** api update ([d19b34e](https://github.com/onlyfansapi/onlyfansapi-python/commit/d19b34eb66ef42f568b9d93e1bd3a75a2e2e841c))
+* **api:** api update ([39eabdf](https://github.com/onlyfansapi/onlyfansapi-python/commit/39eabdf3aa114aefab93cd6d62bb3c55e573d5f7))
+* **api:** api update ([661fcbb](https://github.com/onlyfansapi/onlyfansapi-python/commit/661fcbb83e78132732f94a2fa03ba0d946b7a924))
+* **api:** api update ([3045117](https://github.com/onlyfansapi/onlyfansapi-python/commit/304511738133992687cbe662a050ef7601886cb3))
+* **api:** api update ([8f04ca3](https://github.com/onlyfansapi/onlyfansapi-python/commit/8f04ca304dcd6a9c87a8e754147bf94f3f74e145))
+* **api:** api update ([0b39e31](https://github.com/onlyfansapi/onlyfansapi-python/commit/0b39e3184b3f54a930e11724881f5ca4b89b7405))
+* **api:** api update ([71220c9](https://github.com/onlyfansapi/onlyfansapi-python/commit/71220c909703a5f8da6eee5713682ebaf53df63e))
+* **api:** api update ([5bfca35](https://github.com/onlyfansapi/onlyfansapi-python/commit/5bfca356b7868b864ef49dc0aa4f77fe6ae73aa3))
+* **api:** api update ([1fed67f](https://github.com/onlyfansapi/onlyfansapi-python/commit/1fed67f63373d363e1bacb35db41929479c5d09f))
+* **api:** api update ([d42b221](https://github.com/onlyfansapi/onlyfansapi-python/commit/d42b2211fc03d932c9ca8e94ac562f42f706e4b9))
+* **api:** api update ([2d4e1d9](https://github.com/onlyfansapi/onlyfansapi-python/commit/2d4e1d9147ca5247b796c0100fb2bb05c4618f46))
+* **api:** api update ([56d3af6](https://github.com/onlyfansapi/onlyfansapi-python/commit/56d3af65bb3977a2fe5e4ba229cff154cd5fd3b6))
+* **api:** api update ([afd3835](https://github.com/onlyfansapi/onlyfansapi-python/commit/afd3835d291685dc853fb3d65912f56dc623c485))
+* **api:** api update ([bbaa897](https://github.com/onlyfansapi/onlyfansapi-python/commit/bbaa89714c89ec78261079236b42f2d5d1ddb930))
+* **api:** api update ([06c6eef](https://github.com/onlyfansapi/onlyfansapi-python/commit/06c6eefd0f8f8cb4ee28d7977dd27e594f14c155))
+* **api:** api update ([a96c6d7](https://github.com/onlyfansapi/onlyfansapi-python/commit/a96c6d73c2a5f5dfed976f2ec235b082c2569872))
+* **api:** api update ([eb632d4](https://github.com/onlyfansapi/onlyfansapi-python/commit/eb632d41920d0f838135d5f1d66502298b430bcc))
+* **api:** api update ([6b9ad4e](https://github.com/onlyfansapi/onlyfansapi-python/commit/6b9ad4e06d8663bb4a7959432dbdd1f253b3436e))
+* **api:** api update ([98a84e7](https://github.com/onlyfansapi/onlyfansapi-python/commit/98a84e77ee2bf89462136939c7b6ddfd39a0c619))
+* **api:** api update ([f0a25cd](https://github.com/onlyfansapi/onlyfansapi-python/commit/f0a25cd6b38cdae7c64dfeb113c489b216dda816))
+* **api:** api update ([8bbc9d6](https://github.com/onlyfansapi/onlyfansapi-python/commit/8bbc9d67d84d394af2936841c24ca07f5cce0944))
+* **api:** api update ([3551f5f](https://github.com/onlyfansapi/onlyfansapi-python/commit/3551f5fbba68388f3c5215acec8488b22b83bf30))
+* **api:** api update ([57a911a](https://github.com/onlyfansapi/onlyfansapi-python/commit/57a911acb35d93fd2586a5ae34cc6fd708943b2e))
+* **api:** api update ([e64239d](https://github.com/onlyfansapi/onlyfansapi-python/commit/e64239d0f6358f959e78a679908eddb39f8bff21))
+* **api:** api update ([aa704e0](https://github.com/onlyfansapi/onlyfansapi-python/commit/aa704e0fa956d67a1551857fecfbceaf52a42b5c))
+* **api:** api update ([8ada88c](https://github.com/onlyfansapi/onlyfansapi-python/commit/8ada88cd402259d9daa8cd20e95e3b44d67e0bf5))
+* **api:** api update ([924de03](https://github.com/onlyfansapi/onlyfansapi-python/commit/924de03411c4481b1bf81c6b67dad9d5640c0916))
+* **api:** api update ([fe65d3e](https://github.com/onlyfansapi/onlyfansapi-python/commit/fe65d3ebaaf73dd96c60fbb8dd96292e8b13ae5a))
+* **api:** api update ([b466abb](https://github.com/onlyfansapi/onlyfansapi-python/commit/b466abb391150e3ce362ab9846f672facc69551f))
+* **api:** api update ([db0732e](https://github.com/onlyfansapi/onlyfansapi-python/commit/db0732e227750931db1a25a278456fd7b95424fb))
+* **api:** api update ([2952e4b](https://github.com/onlyfansapi/onlyfansapi-python/commit/2952e4b60838f01d8bd0e586249cd917d607cb62))
+* **api:** api update ([de81294](https://github.com/onlyfansapi/onlyfansapi-python/commit/de812940595d4332b9f42d267f88f12c9783db1a))
+* **api:** api update ([9e94503](https://github.com/onlyfansapi/onlyfansapi-python/commit/9e9450351d93e7a6bd02ac847569349ec71fddb5))
+* **api:** api update ([43194d7](https://github.com/onlyfansapi/onlyfansapi-python/commit/43194d71262d5d50f797a8ccba2659a6c3c2887f))
+* **api:** api update ([4594ec1](https://github.com/onlyfansapi/onlyfansapi-python/commit/4594ec136232b42f3d456b09516ec08065fdfafd))
+* **api:** api update ([c06f3ab](https://github.com/onlyfansapi/onlyfansapi-python/commit/c06f3abf1381148f5e48b85f0086b1af17e2a0d3))
+* **api:** api update ([3525475](https://github.com/onlyfansapi/onlyfansapi-python/commit/3525475272b3341f91f4b75160f63b106321e139))
+* **api:** api update ([3e7e17b](https://github.com/onlyfansapi/onlyfansapi-python/commit/3e7e17b1e3ab8993aba06ffec2ef5378d18f93d2))
+* **api:** api update ([62090dc](https://github.com/onlyfansapi/onlyfansapi-python/commit/62090dc02ca59eb6efec90625d71d312043b55a1))
+* **api:** api update ([9ce94a8](https://github.com/onlyfansapi/onlyfansapi-python/commit/9ce94a833a666de930b770d1ba2c59596ff2d330))
+* **api:** api update ([cb29cb5](https://github.com/onlyfansapi/onlyfansapi-python/commit/cb29cb5216eaf0bbbc57186287b11e829710b6a1))
+* **api:** api update ([43559da](https://github.com/onlyfansapi/onlyfansapi-python/commit/43559da1af5ee18c58b99677f3cfd559e0e2106e))
+* **api:** api update ([9ffc9d3](https://github.com/onlyfansapi/onlyfansapi-python/commit/9ffc9d354f805880d3363c4084fe49935a7a9d10))
+* **api:** api update ([0942b23](https://github.com/onlyfansapi/onlyfansapi-python/commit/0942b231431790866d93cc2e477082c5aee0b87c))
+* **api:** api update ([88c6d42](https://github.com/onlyfansapi/onlyfansapi-python/commit/88c6d42c3c75411714bd70c03322d76b7960208a))
+* **api:** api update ([af71d0c](https://github.com/onlyfansapi/onlyfansapi-python/commit/af71d0ce89f943af5d27d66a5fbb1cd8e7285f9b))
+* **api:** api update ([015b0d1](https://github.com/onlyfansapi/onlyfansapi-python/commit/015b0d11070c3801c8bb26ff99b2f7f1d9ad5627))
+* **api:** api update ([0babea3](https://github.com/onlyfansapi/onlyfansapi-python/commit/0babea32599dc9d8603ba9e6519f9760367ad1f6))
+* **api:** api update ([196b012](https://github.com/onlyfansapi/onlyfansapi-python/commit/196b0123732493210c74e905d55c82ceafee11b9))
+* **api:** api update ([2c2c2d5](https://github.com/onlyfansapi/onlyfansapi-python/commit/2c2c2d5611f7d22371608b4e105d702fc96cbbd1))
+* **api:** api update ([0a74e45](https://github.com/onlyfansapi/onlyfansapi-python/commit/0a74e45ef5ecbefdfb4b2d3ca47c04004f77ee18))
+* **api:** api update ([2b072d1](https://github.com/onlyfansapi/onlyfansapi-python/commit/2b072d1cb4c48b00c3cd66616334e9edd580899d))
+* **api:** api update ([f2f2094](https://github.com/onlyfansapi/onlyfansapi-python/commit/f2f2094213516b1f79af9f22dc03a84a2a074a1a))
+* **api:** api update ([d22aec4](https://github.com/onlyfansapi/onlyfansapi-python/commit/d22aec4906882366899e5bef242bc1a6ca3ca7d6))
+* **api:** api update ([a67bd8b](https://github.com/onlyfansapi/onlyfansapi-python/commit/a67bd8b1e7a96890aaf430233e80dcebf94e6aa0))
+* **api:** api update ([4b08bce](https://github.com/onlyfansapi/onlyfansapi-python/commit/4b08bcecf591dcc5d35dad618d89d806cddab4b8))
+* **stlc:** configurable CI runner and private-production-repo support in workflow templates ([f3bde0a](https://github.com/onlyfansapi/onlyfansapi-python/commit/f3bde0a8124ec521bbb26d670359d590a5b3c532))
+
+
+### Bug Fixes
+
+* **auth:** prioritize first auth header ([ab97425](https://github.com/onlyfansapi/onlyfansapi-python/commit/ab9742585886846cff053430684a5881ec1540bc))
+* **internal:** resolve build failures ([0b55736](https://github.com/onlyfansapi/onlyfansapi-python/commit/0b55736eca40e10bd1e7a690e686fd157f9cba47))
+
## 0.1.2 (2026-05-25)
Full Changelog: [v0.1.1...v0.1.2](https://github.com/onlyfansapi/onlyfansapi-python/compare/v0.1.1...v0.1.2)
diff --git a/api.md b/api.md
index f704b20c..39147900 100644
--- a/api.md
+++ b/api.md
@@ -233,18 +233,6 @@ Methods:
- client.chats.mark_all_as_read.all(account) -> MarkAllAsReadAllResponse
-# Messages
-
-Types:
-
-```python
-from onlyfansapi.types import MessageAttachTagsResponse
-```
-
-Methods:
-
-- client.messages.attach_tags(message_id, \*, account, \*\*params) -> MessageAttachTagsResponse
-
# ClientSessions
Types:
@@ -520,12 +508,12 @@ Methods:
Types:
```python
-from onlyfansapi.types import MediaDownloadResponse, MediaScrapeResponse, MediaUploadResponse
+from onlyfansapi.types import MediaScrapeResponse, MediaUploadResponse
```
Methods:
-- client.media.download(cdn_url, \*, account) -> str
+- client.media.download(cdn_url, \*, account) -> None
- client.media.scrape(account, \*\*params) -> MediaScrapeResponse
- client.media.upload(account, \*\*params) -> MediaUploadResponse
@@ -579,7 +567,7 @@ Methods:
- client.media.vault.lists.create(account, \*\*params) -> ListCreateResponse
- client.media.vault.lists.retrieve(list_id, \*, account) -> ListRetrieveResponse
-- client.media.vault.lists.update(list_id, \*, account) -> ListUpdateResponse
+- client.media.vault.lists.update(list_id, \*, account, \*\*params) -> ListUpdateResponse
- client.media.vault.lists.list(account, \*\*params) -> ListListResponse
- client.media.vault.lists.delete(list_id, \*, account) -> ListDeleteResponse
diff --git a/pyproject.toml b/pyproject.toml
index 184c99e0..856f0210 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "onlyfans"
-version = "0.1.2"
+version = "0.2.0"
description = "The official Python library for the OnlyFansAPI API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/scripts/lint b/scripts/lint
index bc4f4dd7..b8da4f0e 100755
--- a/scripts/lint
+++ b/scripts/lint
@@ -13,7 +13,7 @@ else
fi
echo "==> Running pyright"
-uv run pyright
+uv run pyright -p .
echo "==> Running mypy"
uv run mypy .
diff --git a/src/onlyfansapi/_client.py b/src/onlyfansapi/_client.py
index 4fd6cdfc..00d71ffd 100644
--- a/src/onlyfansapi/_client.py
+++ b/src/onlyfansapi/_client.py
@@ -53,7 +53,6 @@
payouts,
stories,
accounts,
- messages,
profiles,
settings,
webhooks,
@@ -90,7 +89,6 @@
from .resources.bundles import BundlesResource, AsyncBundlesResource
from .resources.payouts import PayoutsResource, AsyncPayoutsResource
from .resources.accounts import AccountsResource, AsyncAccountsResource
- from .resources.messages import MessagesResource, AsyncMessagesResource
from .resources.profiles import ProfilesResource, AsyncProfilesResource
from .resources.webhooks import WebhooksResource, AsyncWebhooksResource
from .resources.fans.fans import FansResource, AsyncFansResource
@@ -251,12 +249,6 @@ def chats(self) -> ChatsResource:
return ChatsResource(self)
- @cached_property
- def messages(self) -> MessagesResource:
- from .resources.messages import MessagesResource
-
- return MessagesResource(self)
-
@cached_property
def client_sessions(self) -> ClientSessionsResource:
from .resources.client_sessions import ClientSessionsResource
@@ -311,7 +303,7 @@ def giphy(self) -> GiphyResource:
@cached_property
def link_tags(self) -> LinkTagsResource:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import LinkTagsResource
return LinkTagsResource(self)
@@ -505,9 +497,11 @@ def qs(self) -> Querystring:
@override
def _auth_headers(self, security: SecurityOptions) -> dict[str, str]:
- return {
- **(self._default if security.get("default", False) else {}),
- }
+ headers: dict[str, str] = {}
+ if security.get("default", False):
+ for key, value in self._default.items():
+ headers.setdefault(key, value)
+ return headers
@property
def _default(self) -> dict[str, str]:
@@ -719,12 +713,6 @@ def chats(self) -> AsyncChatsResource:
return AsyncChatsResource(self)
- @cached_property
- def messages(self) -> AsyncMessagesResource:
- from .resources.messages import AsyncMessagesResource
-
- return AsyncMessagesResource(self)
-
@cached_property
def client_sessions(self) -> AsyncClientSessionsResource:
from .resources.client_sessions import AsyncClientSessionsResource
@@ -779,7 +767,7 @@ def giphy(self) -> AsyncGiphyResource:
@cached_property
def link_tags(self) -> AsyncLinkTagsResource:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import AsyncLinkTagsResource
return AsyncLinkTagsResource(self)
@@ -973,9 +961,11 @@ def qs(self) -> Querystring:
@override
def _auth_headers(self, security: SecurityOptions) -> dict[str, str]:
- return {
- **(self._default if security.get("default", False) else {}),
- }
+ headers: dict[str, str] = {}
+ if security.get("default", False):
+ for key, value in self._default.items():
+ headers.setdefault(key, value)
+ return headers
@property
def _default(self) -> dict[str, str]:
@@ -1129,12 +1119,6 @@ def chats(self) -> chats.ChatsResourceWithRawResponse:
return ChatsResourceWithRawResponse(self._client.chats)
- @cached_property
- def messages(self) -> messages.MessagesResourceWithRawResponse:
- from .resources.messages import MessagesResourceWithRawResponse
-
- return MessagesResourceWithRawResponse(self._client.messages)
-
@cached_property
def client_sessions(self) -> client_sessions.ClientSessionsResourceWithRawResponse:
from .resources.client_sessions import ClientSessionsResourceWithRawResponse
@@ -1189,7 +1173,7 @@ def giphy(self) -> giphy.GiphyResourceWithRawResponse:
@cached_property
def link_tags(self) -> link_tags.LinkTagsResourceWithRawResponse:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import LinkTagsResourceWithRawResponse
return LinkTagsResourceWithRawResponse(self._client.link_tags)
@@ -1422,12 +1406,6 @@ def chats(self) -> chats.AsyncChatsResourceWithRawResponse:
return AsyncChatsResourceWithRawResponse(self._client.chats)
- @cached_property
- def messages(self) -> messages.AsyncMessagesResourceWithRawResponse:
- from .resources.messages import AsyncMessagesResourceWithRawResponse
-
- return AsyncMessagesResourceWithRawResponse(self._client.messages)
-
@cached_property
def client_sessions(self) -> client_sessions.AsyncClientSessionsResourceWithRawResponse:
from .resources.client_sessions import AsyncClientSessionsResourceWithRawResponse
@@ -1482,7 +1460,7 @@ def giphy(self) -> giphy.AsyncGiphyResourceWithRawResponse:
@cached_property
def link_tags(self) -> link_tags.AsyncLinkTagsResourceWithRawResponse:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import AsyncLinkTagsResourceWithRawResponse
return AsyncLinkTagsResourceWithRawResponse(self._client.link_tags)
@@ -1715,12 +1693,6 @@ def chats(self) -> chats.ChatsResourceWithStreamingResponse:
return ChatsResourceWithStreamingResponse(self._client.chats)
- @cached_property
- def messages(self) -> messages.MessagesResourceWithStreamingResponse:
- from .resources.messages import MessagesResourceWithStreamingResponse
-
- return MessagesResourceWithStreamingResponse(self._client.messages)
-
@cached_property
def client_sessions(self) -> client_sessions.ClientSessionsResourceWithStreamingResponse:
from .resources.client_sessions import ClientSessionsResourceWithStreamingResponse
@@ -1775,7 +1747,7 @@ def giphy(self) -> giphy.GiphyResourceWithStreamingResponse:
@cached_property
def link_tags(self) -> link_tags.LinkTagsResourceWithStreamingResponse:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import LinkTagsResourceWithStreamingResponse
return LinkTagsResourceWithStreamingResponse(self._client.link_tags)
@@ -2008,12 +1980,6 @@ def chats(self) -> chats.AsyncChatsResourceWithStreamingResponse:
return AsyncChatsResourceWithStreamingResponse(self._client.chats)
- @cached_property
- def messages(self) -> messages.AsyncMessagesResourceWithStreamingResponse:
- from .resources.messages import AsyncMessagesResourceWithStreamingResponse
-
- return AsyncMessagesResourceWithStreamingResponse(self._client.messages)
-
@cached_property
def client_sessions(self) -> client_sessions.AsyncClientSessionsResourceWithStreamingResponse:
from .resources.client_sessions import AsyncClientSessionsResourceWithStreamingResponse
@@ -2068,7 +2034,7 @@ def giphy(self) -> giphy.AsyncGiphyResourceWithStreamingResponse:
@cached_property
def link_tags(self) -> link_tags.AsyncLinkTagsResourceWithStreamingResponse:
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
from .resources.link_tags import AsyncLinkTagsResourceWithStreamingResponse
return AsyncLinkTagsResourceWithStreamingResponse(self._client.link_tags)
diff --git a/src/onlyfansapi/_version.py b/src/onlyfansapi/_version.py
index 790de9b3..a6edd998 100644
--- a/src/onlyfansapi/_version.py
+++ b/src/onlyfansapi/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "onlyfansapi"
-__version__ = "0.1.2" # x-release-please-version
+__version__ = "0.2.0" # x-release-please-version
diff --git a/src/onlyfansapi/resources/__init__.py b/src/onlyfansapi/resources/__init__.py
index 00eec24d..60042b7d 100644
--- a/src/onlyfansapi/resources/__init__.py
+++ b/src/onlyfansapi/resources/__init__.py
@@ -128,14 +128,6 @@
AccountsResourceWithStreamingResponse,
AsyncAccountsResourceWithStreamingResponse,
)
-from .messages import (
- MessagesResource,
- AsyncMessagesResource,
- MessagesResourceWithRawResponse,
- AsyncMessagesResourceWithRawResponse,
- MessagesResourceWithStreamingResponse,
- AsyncMessagesResourceWithStreamingResponse,
-)
from .profiles import (
ProfilesResource,
AsyncProfilesResource,
@@ -388,12 +380,6 @@
"AsyncChatsResourceWithRawResponse",
"ChatsResourceWithStreamingResponse",
"AsyncChatsResourceWithStreamingResponse",
- "MessagesResource",
- "AsyncMessagesResource",
- "MessagesResourceWithRawResponse",
- "AsyncMessagesResourceWithRawResponse",
- "MessagesResourceWithStreamingResponse",
- "AsyncMessagesResourceWithStreamingResponse",
"ClientSessionsResource",
"AsyncClientSessionsResource",
"ClientSessionsResourceWithRawResponse",
diff --git a/src/onlyfansapi/resources/authenticate.py b/src/onlyfansapi/resources/authenticate.py
index aae19208..d97b35b7 100644
--- a/src/onlyfansapi/resources/authenticate.py
+++ b/src/onlyfansapi/resources/authenticate.py
@@ -165,7 +165,7 @@ def start(
force_connect: bool | Omit = omit,
name: str | Omit = omit,
password: str | Omit = omit,
- proxy_country: Literal["us", "uk"] | Omit = omit,
+ proxy_country: Literal["us", "uk", "gb"] | Omit = omit,
user_agent: str | Omit = omit,
xbc: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -440,7 +440,7 @@ async def start(
force_connect: bool | Omit = omit,
name: str | Omit = omit,
password: str | Omit = omit,
- proxy_country: Literal["us", "uk"] | Omit = omit,
+ proxy_country: Literal["us", "uk", "gb"] | Omit = omit,
user_agent: str | Omit = omit,
xbc: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
diff --git a/src/onlyfansapi/resources/chats/chats.py b/src/onlyfansapi/resources/chats/chats.py
index 2e50426d..07495710 100644
--- a/src/onlyfansapi/resources/chats/chats.py
+++ b/src/onlyfansapi/resources/chats/chats.py
@@ -107,7 +107,8 @@ def list(
query: Search query to filter chats
- skip_users: Whether to skip user details in response (all or none). Default = all
+ skip_users: Whether to skip user details in the response (`all` or `none`). Defaults to
+ `all`.
extra_headers: Send extra headers
@@ -239,7 +240,8 @@ def list_media(
offset: Number of medias to skip for pagination
- skip_users: Whether to skip user details in response (all or none). Default = all
+ skip_users: Whether to skip user details in the response (`all` or `none`). Defaults to
+ `all`.
type: Filter by specific media types. Keep empty to return all.
@@ -399,8 +401,8 @@ def start_typing(
) -> ChatStartTypingResponse:
"""
Calling this endpoint will show the target fan a "Model is typing..." note in
- the chat for ~4 seconds. If you want to continue showing the indicator call this
- endpoint multiple times. Free - no credits charged.
+ the chat for ~4 seconds. Duplicate calls for the same account and chat are
+ coalesced during that window.
Args:
extra_headers: Send extra headers
@@ -519,7 +521,8 @@ async def list(
query: Search query to filter chats
- skip_users: Whether to skip user details in response (all or none). Default = all
+ skip_users: Whether to skip user details in the response (`all` or `none`). Defaults to
+ `all`.
extra_headers: Send extra headers
@@ -651,7 +654,8 @@ async def list_media(
offset: Number of medias to skip for pagination
- skip_users: Whether to skip user details in response (all or none). Default = all
+ skip_users: Whether to skip user details in the response (`all` or `none`). Defaults to
+ `all`.
type: Filter by specific media types. Keep empty to return all.
@@ -811,8 +815,8 @@ async def start_typing(
) -> ChatStartTypingResponse:
"""
Calling this endpoint will show the target fan a "Model is typing..." note in
- the chat for ~4 seconds. If you want to continue showing the indicator call this
- endpoint multiple times. Free - no credits charged.
+ the chat for ~4 seconds. Duplicate calls for the same account and chat are
+ coalesced during that window.
Args:
extra_headers: Send extra headers
diff --git a/src/onlyfansapi/resources/chats/messages.py b/src/onlyfansapi/resources/chats/messages.py
index b03a0f97..22a57b19 100644
--- a/src/onlyfansapi/resources/chats/messages.py
+++ b/src/onlyfansapi/resources/chats/messages.py
@@ -8,7 +8,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -136,7 +136,7 @@ def list(
order: Sort order for messages (desc or asc)
- skip_users: Whether to skip user details (all or none)
+ skip_users: Whether to skip user details (`all` or `none`).
extra_headers: Send extra headers
@@ -356,16 +356,18 @@ def send(
chat_id: str,
*,
account: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: Iterable[object] | Omit = omit,
previews: Iterable[object] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
reply_to_message_id: int | Omit = omit,
rf_guest: str | Omit = omit,
rf_partner: str | Omit = omit,
rf_tag: str | Omit = omit,
text: str | Omit = omit,
+ idempotency_key: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -376,7 +378,36 @@ def send(
"""
Send a new message to a chat.
+ **Idempotency.** Pass an `Idempotency-Key` header to make retries safe. The
+ first request with a given key is executed normally and its response is stored
+ for **24 hours**; any later request with the same key returns that stored
+ response, plus an `Idempotent-Replayed: true` header, without contacting
+ OnlyFans and without consuming credits. The replayed body is the original
+ response with its `_meta._credits` block rewritten to show `used: 0` and your
+ current balance.
+
+ Keys are scoped to your team, this endpoint and the account in the URL, so the
+ same value can be reused safely against a different account. Use a fresh, unique
+ value (a UUID works well) for each message you send; it must be 1-255 printable
+ ASCII characters.
+
+ - `400 IDEMPOTENCY_KEY_INVALID` — the header value is empty, too long, or
+ contains non-ASCII characters.
+ - `409 IDEMPOTENCY_CONFLICT` — an earlier request with this key is still
+ running. Retry once it finishes.
+ - `422 IDEMPOTENCY_KEY_MISMATCH` — this key was already used with a different
+ request body or chat.
+
+ Responses with a `5xx` status (and `408`/`429`) are never stored, so a failed
+ send can be retried with the same key. The header is optional: omit it and the
+ endpoint behaves exactly as before.
+
Args:
+ block_banned_words: Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
endpoints (`/giphy/trending`, `/giphy/search`).
@@ -389,7 +420,7 @@ def send(
referencing uploaded files in `mediaFiles`. Will be shown if `price` is
provided.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
reply_to_message_id: Mark this message as a reply to another (can be either your own, or the
@@ -415,10 +446,12 @@ def send(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
return self._post(
path_template("/api/{account}/chats/{chat_id}/messages", account=account, chat_id=chat_id),
body=maybe_transform(
{
+ "block_banned_words": block_banned_words,
"giphy_id": giphy_id,
"locked_text": locked_text,
"media_files": media_files,
@@ -631,7 +664,7 @@ async def list(
order: Sort order for messages (desc or asc)
- skip_users: Whether to skip user details (all or none)
+ skip_users: Whether to skip user details (`all` or `none`).
extra_headers: Send extra headers
@@ -851,16 +884,18 @@ async def send(
chat_id: str,
*,
account: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: Iterable[object] | Omit = omit,
previews: Iterable[object] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
reply_to_message_id: int | Omit = omit,
rf_guest: str | Omit = omit,
rf_partner: str | Omit = omit,
rf_tag: str | Omit = omit,
text: str | Omit = omit,
+ idempotency_key: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -871,7 +906,36 @@ async def send(
"""
Send a new message to a chat.
+ **Idempotency.** Pass an `Idempotency-Key` header to make retries safe. The
+ first request with a given key is executed normally and its response is stored
+ for **24 hours**; any later request with the same key returns that stored
+ response, plus an `Idempotent-Replayed: true` header, without contacting
+ OnlyFans and without consuming credits. The replayed body is the original
+ response with its `_meta._credits` block rewritten to show `used: 0` and your
+ current balance.
+
+ Keys are scoped to your team, this endpoint and the account in the URL, so the
+ same value can be reused safely against a different account. Use a fresh, unique
+ value (a UUID works well) for each message you send; it must be 1-255 printable
+ ASCII characters.
+
+ - `400 IDEMPOTENCY_KEY_INVALID` — the header value is empty, too long, or
+ contains non-ASCII characters.
+ - `409 IDEMPOTENCY_CONFLICT` — an earlier request with this key is still
+ running. Retry once it finishes.
+ - `422 IDEMPOTENCY_KEY_MISMATCH` — this key was already used with a different
+ request body or chat.
+
+ Responses with a `5xx` status (and `408`/`429`) are never stored, so a failed
+ send can be retried with the same key. The header is optional: omit it and the
+ endpoint behaves exactly as before.
+
Args:
+ block_banned_words: Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
endpoints (`/giphy/trending`, `/giphy/search`).
@@ -884,7 +948,7 @@ async def send(
referencing uploaded files in `mediaFiles`. Will be shown if `price` is
provided.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
reply_to_message_id: Mark this message as a reply to another (can be either your own, or the
@@ -910,10 +974,12 @@ async def send(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
return await self._post(
path_template("/api/{account}/chats/{chat_id}/messages", account=account, chat_id=chat_id),
body=await async_maybe_transform(
{
+ "block_banned_words": block_banned_words,
"giphy_id": giphy_id,
"locked_text": locked_text,
"media_files": media_files,
diff --git a/src/onlyfansapi/resources/client_sessions.py b/src/onlyfansapi/resources/client_sessions.py
index c1ea87e0..38a1d318 100644
--- a/src/onlyfansapi/resources/client_sessions.py
+++ b/src/onlyfansapi/resources/client_sessions.py
@@ -49,7 +49,7 @@ def create(
*,
display_name: str,
client_reference_id: str | Omit = omit,
- proxy_country: Optional[Literal["us", "uk"]] | Omit = omit,
+ proxy_country: Optional[Literal["us", "uk", "gb"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -117,7 +117,7 @@ async def create(
*,
display_name: str,
client_reference_id: str | Omit = omit,
- proxy_country: Optional[Literal["us", "uk"]] | Omit = omit,
+ proxy_country: Optional[Literal["us", "uk", "gb"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
diff --git a/src/onlyfansapi/resources/data_exports.py b/src/onlyfansapi/resources/data_exports.py
index 2eaf7c0e..54c0baa0 100644
--- a/src/onlyfansapi/resources/data_exports.py
+++ b/src/onlyfansapi/resources/data_exports.py
@@ -69,6 +69,8 @@ def create(
"public_profiles",
"fans",
"followings",
+ "profile_visitors",
+ "fansly_chat_messages",
],
account_ids: SequenceNotStr[str] | Omit = omit,
auto_start: bool | Omit = omit,
@@ -90,15 +92,20 @@ def create(
end_date: The end date for the export (ISO 8601 format).
file_type: The output file format. Supported formats vary by export type: `csv` or `xlsx`
- for transactions, chat_messages, trial_links, tracking_links, smart_links,
- payouts, chargebacks, public_profiles, fans, followings; `zip` for media_vault.
+ for transactions, chat_messages, fansly_chat_messages, trial_links,
+ tracking_links, smart_links, payouts, chargebacks, public_profiles, fans,
+ followings, profile_visitors; `zip` for media_vault.
start_date: The start date for the export (ISO 8601 format).
- type: The type of data to export
+ type: The type of data to export. Use `fansly_chat_messages` to export Fansly chat
+ messages (all other types are OnlyFans). `profile_visitors` returns one row per
+ account per day, scraped one day at a time so the daily numbers are not
+ aggregated away by OnlyFans.
account_ids: Array of account prefixed IDs to export data from. Not required for
- `public_profiles` type.
+ `public_profiles` type. For `fansly_chat_messages`, pass Fansly account prefixed
+ IDs (`fansly_acct_...`); all other types take OnlyFans account IDs.
auto_start: When true, automatically starts the export after creation.
@@ -109,19 +116,23 @@ def create(
account, max 10,000,000), `maxChats` (optional per-account chat scrape limit),
`skipMassMessages` (optional, bool), `chatIds` (optional array of numeric
fan/chat IDs; filters output and can drastically reduce totals). For
- `media_vault`: `mediaType` (required, one of: `all`, `photo`, `gif`, `video`,
- `audio`). For `fans`: `type` (required, one of: `all`, `active`, `expired`,
- `latest`). For `followings`: `type` (required, one of: `all`, `active`,
- `expired`). For `public_profiles`: `query` (optional, full-text search),
- `gender` (optional, filter: male, female, trans, couple), `minSubscribePrice`
- (optional, USD), `maxSubscribePrice` (optional, USD), `location` (optional),
- `minPostsCount` (optional, minimum posts), `minPhotosCount` (optional, minimum
- photos), `minVideosCount` (optional, minimum videos), `minSubscribersCount`
- (optional, minimum subscribers), `minJoinDate` (optional, ISO 8601 date),
- `minLastSeenAt` (optional, ISO 8601 date), `createdAtFrom` (optional, ISO 8601
- date, profile added to DB after), `createdAtTo` (optional, ISO 8601 date,
- profile added to DB before), `instagram` (optional), `twitter` (optional),
- `tiktok` (optional), `maxResults` (optional, limit results).
+ `fansly_chat_messages`: `maxMessages` (required per account, max 10,000,000),
+ `maxChats` (optional per-account chat scrape limit), `chatIds` (optional array
+ of Fansly group ID strings; filters output and can drastically reduce totals).
+ For `media_vault`: `mediaType` (required, one of: `all`, `photo`, `gif`,
+ `video`, `audio`). For `fans`: `type` (required, one of: `all`, `active`,
+ `expired`, `latest`). For `followings`: `type` (required, one of: `all`,
+ `active`, `expired`). For `public_profiles`: `query` (optional, full-text
+ search), `gender` (optional, filter: male, female, trans, couple),
+ `minSubscribePrice` (optional, USD), `maxSubscribePrice` (optional, USD),
+ `location` (optional), `minPostsCount` (optional, minimum posts),
+ `minPhotosCount` (optional, minimum photos), `minVideosCount` (optional, minimum
+ videos), `minSubscribersCount` (optional, minimum subscribers),
+ `maxSubscribersCount` (optional, maximum subscribers), `minJoinDate` (optional,
+ ISO 8601 date), `minLastSeenAt` (optional, ISO 8601 date), `createdAtFrom`
+ (optional, ISO 8601 date, profile added to DB after), `createdAtTo` (optional,
+ ISO 8601 date, profile added to DB before), `instagram` (optional), `twitter`
+ (optional), `tiktok` (optional), `maxResults` (optional, limit results).
extra_headers: Send extra headers
@@ -218,9 +229,14 @@ def list(
"media_vault",
"trial_links",
"tracking_links",
+ "smart_links",
"payouts",
"chargebacks",
"public_profiles",
+ "fans",
+ "followings",
+ "profile_visitors",
+ "fansly_chat_messages",
]
| Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -418,6 +434,8 @@ async def create(
"public_profiles",
"fans",
"followings",
+ "profile_visitors",
+ "fansly_chat_messages",
],
account_ids: SequenceNotStr[str] | Omit = omit,
auto_start: bool | Omit = omit,
@@ -439,15 +457,20 @@ async def create(
end_date: The end date for the export (ISO 8601 format).
file_type: The output file format. Supported formats vary by export type: `csv` or `xlsx`
- for transactions, chat_messages, trial_links, tracking_links, smart_links,
- payouts, chargebacks, public_profiles, fans, followings; `zip` for media_vault.
+ for transactions, chat_messages, fansly_chat_messages, trial_links,
+ tracking_links, smart_links, payouts, chargebacks, public_profiles, fans,
+ followings, profile_visitors; `zip` for media_vault.
start_date: The start date for the export (ISO 8601 format).
- type: The type of data to export
+ type: The type of data to export. Use `fansly_chat_messages` to export Fansly chat
+ messages (all other types are OnlyFans). `profile_visitors` returns one row per
+ account per day, scraped one day at a time so the daily numbers are not
+ aggregated away by OnlyFans.
account_ids: Array of account prefixed IDs to export data from. Not required for
- `public_profiles` type.
+ `public_profiles` type. For `fansly_chat_messages`, pass Fansly account prefixed
+ IDs (`fansly_acct_...`); all other types take OnlyFans account IDs.
auto_start: When true, automatically starts the export after creation.
@@ -458,19 +481,23 @@ async def create(
account, max 10,000,000), `maxChats` (optional per-account chat scrape limit),
`skipMassMessages` (optional, bool), `chatIds` (optional array of numeric
fan/chat IDs; filters output and can drastically reduce totals). For
- `media_vault`: `mediaType` (required, one of: `all`, `photo`, `gif`, `video`,
- `audio`). For `fans`: `type` (required, one of: `all`, `active`, `expired`,
- `latest`). For `followings`: `type` (required, one of: `all`, `active`,
- `expired`). For `public_profiles`: `query` (optional, full-text search),
- `gender` (optional, filter: male, female, trans, couple), `minSubscribePrice`
- (optional, USD), `maxSubscribePrice` (optional, USD), `location` (optional),
- `minPostsCount` (optional, minimum posts), `minPhotosCount` (optional, minimum
- photos), `minVideosCount` (optional, minimum videos), `minSubscribersCount`
- (optional, minimum subscribers), `minJoinDate` (optional, ISO 8601 date),
- `minLastSeenAt` (optional, ISO 8601 date), `createdAtFrom` (optional, ISO 8601
- date, profile added to DB after), `createdAtTo` (optional, ISO 8601 date,
- profile added to DB before), `instagram` (optional), `twitter` (optional),
- `tiktok` (optional), `maxResults` (optional, limit results).
+ `fansly_chat_messages`: `maxMessages` (required per account, max 10,000,000),
+ `maxChats` (optional per-account chat scrape limit), `chatIds` (optional array
+ of Fansly group ID strings; filters output and can drastically reduce totals).
+ For `media_vault`: `mediaType` (required, one of: `all`, `photo`, `gif`,
+ `video`, `audio`). For `fans`: `type` (required, one of: `all`, `active`,
+ `expired`, `latest`). For `followings`: `type` (required, one of: `all`,
+ `active`, `expired`). For `public_profiles`: `query` (optional, full-text
+ search), `gender` (optional, filter: male, female, trans, couple),
+ `minSubscribePrice` (optional, USD), `maxSubscribePrice` (optional, USD),
+ `location` (optional), `minPostsCount` (optional, minimum posts),
+ `minPhotosCount` (optional, minimum photos), `minVideosCount` (optional, minimum
+ videos), `minSubscribersCount` (optional, minimum subscribers),
+ `maxSubscribersCount` (optional, maximum subscribers), `minJoinDate` (optional,
+ ISO 8601 date), `minLastSeenAt` (optional, ISO 8601 date), `createdAtFrom`
+ (optional, ISO 8601 date, profile added to DB after), `createdAtTo` (optional,
+ ISO 8601 date, profile added to DB before), `instagram` (optional), `twitter`
+ (optional), `tiktok` (optional), `maxResults` (optional, limit results).
extra_headers: Send extra headers
@@ -567,9 +594,14 @@ async def list(
"media_vault",
"trial_links",
"tracking_links",
+ "smart_links",
"payouts",
"chargebacks",
"public_profiles",
+ "fans",
+ "followings",
+ "profile_visitors",
+ "fansly_chat_messages",
]
| Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
diff --git a/src/onlyfansapi/resources/engagement/messages/direct_messages.py b/src/onlyfansapi/resources/engagement/messages/direct_messages.py
index 1d1a0864..e8d03427 100644
--- a/src/onlyfansapi/resources/engagement/messages/direct_messages.py
+++ b/src/onlyfansapi/resources/engagement/messages/direct_messages.py
@@ -62,8 +62,8 @@ def list(
List sent direct messages with engagement stats (sent, viewed, purchased, etc.).
Args:
- end_date: The latest message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of messages to return (default = 10)
@@ -123,7 +123,7 @@ def chart(
over time.
Args:
- end_date: End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`.
+ end_date: End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`.
start_date: Start of the chart window in `Y-m-d H:i:s` format.
@@ -199,8 +199,8 @@ async def list(
List sent direct messages with engagement stats (sent, viewed, purchased, etc.).
Args:
- end_date: The latest message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of messages to return (default = 10)
@@ -260,7 +260,7 @@ async def chart(
over time.
Args:
- end_date: End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`.
+ end_date: End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`.
start_date: Start of the chart window in `Y-m-d H:i:s` format.
diff --git a/src/onlyfansapi/resources/engagement/messages/mass_messages.py b/src/onlyfansapi/resources/engagement/messages/mass_messages.py
index 80324372..6b5156bc 100644
--- a/src/onlyfansapi/resources/engagement/messages/mass_messages.py
+++ b/src/onlyfansapi/resources/engagement/messages/mass_messages.py
@@ -61,8 +61,8 @@ def list(
List sent mass messages with engagement stats (sent, viewed, purchased, etc.).
Args:
- end_date: The latest message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of messages to return (default = 10)
@@ -119,7 +119,7 @@ def chart(
over time.
Args:
- end_date: End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`.
+ end_date: End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`.
start_date: Start of the chart window in `Y-m-d H:i:s` format.
@@ -194,8 +194,8 @@ async def list(
List sent mass messages with engagement stats (sent, viewed, purchased, etc.).
Args:
- end_date: The latest message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of messages to return (default = 10)
@@ -252,7 +252,7 @@ async def chart(
over time.
Args:
- end_date: End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`.
+ end_date: End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`.
start_date: Start of the chart window in `Y-m-d H:i:s` format.
diff --git a/src/onlyfansapi/resources/engagement/messages/messages.py b/src/onlyfansapi/resources/engagement/messages/messages.py
index d3cb2d0d..2f00767a 100644
--- a/src/onlyfansapi/resources/engagement/messages/messages.py
+++ b/src/onlyfansapi/resources/engagement/messages/messages.py
@@ -93,7 +93,7 @@ def get_message_buyers(
offset: Offset for pagination (default = 0)
- skip_users: Optional flag for subsequent pages (example: all)
+ skip_users: Optional flag for subsequent pages (example: all).
skip_users_dups: Skip duplicate users in results (0/1). Default = 1
@@ -149,8 +149,8 @@ def get_top_message(
Get the top performing message by purchases in the selected timeframe.
Args:
- end_date: The end date for the period. Keep empty to retrieve until now. MUST BE DATE
- AFTER `startDate`.
+ end_date: The end date for the period. Keep empty to retrieve until now. It must be after
+ `startDate`.
start_date: The start date for the period. Keep empty to retrieve from the model start date.
@@ -238,7 +238,7 @@ async def get_message_buyers(
offset: Offset for pagination (default = 0)
- skip_users: Optional flag for subsequent pages (example: all)
+ skip_users: Optional flag for subsequent pages (example: all).
skip_users_dups: Skip duplicate users in results (0/1). Default = 1
@@ -294,8 +294,8 @@ async def get_top_message(
Get the top performing message by purchases in the selected timeframe.
Args:
- end_date: The end date for the period. Keep empty to retrieve until now. MUST BE DATE
- AFTER `startDate`.
+ end_date: The end date for the period. Keep empty to retrieve until now. It must be after
+ `startDate`.
start_date: The start date for the period. Keep empty to retrieve from the model start date.
diff --git a/src/onlyfansapi/resources/fans/fans.py b/src/onlyfansapi/resources/fans/fans.py
index 906a8738..026ff3a8 100644
--- a/src/onlyfansapi/resources/fans/fans.py
+++ b/src/onlyfansapi/resources/fans/fans.py
@@ -141,11 +141,23 @@ def list_active(
) -> FanListActiveResponse:
"""Get a paginated list of fans for an Account.
- Newest fans are first.
+ Newest fans are first. Paginate by
+ following `_pagination.next_page` until it is null (`data.hasMore` is the
+ authoritative flag). Do NOT use the page's item count to detect the last page —
+ OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for limit=20) on
+ a non-final page because it filters entries server-side; no fans are skipped. To
+ track progress, GET `/{account}/me` returns data.subscribersCount (the current
+ active-subscriber count) as a total.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -202,11 +214,21 @@ def list_all(
) -> FanListAllResponse:
"""Get a paginated list of fans for an Account.
- Newest fans are first.
+ Newest fans are first. Paginate by
+ following `_pagination.next_page` until it is null (`data.hasMore` is the
+ authoritative flag). Do NOT use the page's item count to detect the last page —
+ OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for limit=20) on
+ a non-final page because it filters entries server-side; no fans are skipped.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -264,10 +286,21 @@ def list_expired(
"""Get a paginated list of expired fans for an Account.
Newest fans are first.
+ Paginate by following `_pagination.next_page` until it is null (`data.hasMore`
+ is the authoritative flag). Do NOT use the page's item count to detect the last
+ page — OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for
+ limit=20) on a non-final page because it filters entries server-side; no fans
+ are skipped.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -327,16 +360,16 @@ def list_latest(
renewals. Newest fans are first.
Args:
- end_date: End date for filtering (required with start_date). This field is required when
- start_date is present.
+ end_date: End date for filtering (required with start_date). Must be a valid date. Must
+ not be greater than 255 characters.
limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 100.
+ than 50.
offset: Number of fans to skip. Must be at least 0.
- start_date: Start date for filtering (required with end_date). This field is required when
- end_date is present.
+ start_date: Start date for filtering (required with end_date). Must be a valid date. Must
+ not be greater than 255 characters.
type: Filter by type: total, renew, or new.
@@ -393,11 +426,11 @@ def list_top(
Args:
by: Sort by: total (default), subscribes, tips, messages, post, streams.
- end_date: End date for filtering (required with start_date). This field is required when
- start_date is present.
+ end_date: End date for filtering (required with start_date). Must be a valid date. Must
+ not be greater than 255 characters.
- start_date: Start date for filtering (required with end_date). This field is required when
- end_date is present.
+ start_date: Start date for filtering (required with end_date). Must be a valid date. Must
+ not be greater than 255 characters.
extra_headers: Send extra headers
@@ -558,11 +591,23 @@ async def list_active(
) -> FanListActiveResponse:
"""Get a paginated list of fans for an Account.
- Newest fans are first.
+ Newest fans are first. Paginate by
+ following `_pagination.next_page` until it is null (`data.hasMore` is the
+ authoritative flag). Do NOT use the page's item count to detect the last page —
+ OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for limit=20) on
+ a non-final page because it filters entries server-side; no fans are skipped. To
+ track progress, GET `/{account}/me` returns data.subscribersCount (the current
+ active-subscriber count) as a total.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -619,11 +664,21 @@ async def list_all(
) -> FanListAllResponse:
"""Get a paginated list of fans for an Account.
- Newest fans are first.
+ Newest fans are first. Paginate by
+ following `_pagination.next_page` until it is null (`data.hasMore` is the
+ authoritative flag). Do NOT use the page's item count to detect the last page —
+ OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for limit=20) on
+ a non-final page because it filters entries server-side; no fans are skipped.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -681,10 +736,21 @@ async def list_expired(
"""Get a paginated list of expired fans for an Account.
Newest fans are first.
+ Paginate by following `_pagination.next_page` until it is null (`data.hasMore`
+ is the authoritative flag). Do NOT use the page's item count to detect the last
+ page — OnlyFans occasionally returns fewer than `limit` items (e.g. 19 for
+ limit=20) on a non-final page because it filters entries server-side; no fans
+ are skipped.
+
+ Supports `filter[max_total_spent]` (e.g. `filter[max_total_spent]=0` for fans
+ who have never spent), which OnlyFans itself cannot do. Those requests are
+ answered from OnlyFansAPI's own fan index rather than proxied, so the page is
+ limited to fans we have already indexed for this account — see `data._source` in
+ the response.
Args:
- limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 20.
+ limit: Number of fans to return (1-20). OnlyFans does not allow more than 20 per page.
+ Must be at least 1. Must not be greater than 20.
offset: Number of fans to skip. Must be at least 0.
@@ -744,16 +810,16 @@ async def list_latest(
renewals. Newest fans are first.
Args:
- end_date: End date for filtering (required with start_date). This field is required when
- start_date is present.
+ end_date: End date for filtering (required with start_date). Must be a valid date. Must
+ not be greater than 255 characters.
limit: Number of fans to return (1-50). Must be at least 1. Must not be greater
- than 100.
+ than 50.
offset: Number of fans to skip. Must be at least 0.
- start_date: Start date for filtering (required with end_date). This field is required when
- end_date is present.
+ start_date: Start date for filtering (required with end_date). Must be a valid date. Must
+ not be greater than 255 characters.
type: Filter by type: total, renew, or new.
@@ -810,11 +876,11 @@ async def list_top(
Args:
by: Sort by: total (default), subscribes, tips, messages, post, streams.
- end_date: End date for filtering (required with start_date). This field is required when
- start_date is present.
+ end_date: End date for filtering (required with start_date). Must be a valid date. Must
+ not be greater than 255 characters.
- start_date: Start date for filtering (required with end_date). This field is required when
- end_date is present.
+ start_date: Start date for filtering (required with end_date). Must be a valid date. Must
+ not be greater than 255 characters.
extra_headers: Send extra headers
diff --git a/src/onlyfansapi/resources/following.py b/src/onlyfansapi/resources/following.py
index d7294b14..a8845668 100644
--- a/src/onlyfansapi/resources/following.py
+++ b/src/onlyfansapi/resources/following.py
@@ -3,6 +3,7 @@
from __future__ import annotations
from typing import Optional
+from typing_extensions import Literal
import httpx
@@ -55,6 +56,8 @@ def list_active(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -64,7 +67,16 @@ def list_active(
) -> FollowingListActiveResponse:
"""Get a paginated list of followings for an Account.
- Newest followings are first.
+ By default OnlyFans returns
+ this list newest-first, sorted by `subscribedByData.subscribeAt` descending. The
+ expired list does not share this order, so do not assume it applies there. Pass
+ `sort` (optionally with `sortDirection`) to reorder the list — see the parameter
+ description for the caveat that OnlyFans persists the chosen order account-wide.
+ An empty page is not the end of the list: OnlyFans applies `offset` to the whole
+ following collection before filtering it down to the requested list, so a page
+ can come back empty while more results follow. Keep following
+ `_pagination.next_page` until it is `null` instead of stopping at the first
+ empty page.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -74,6 +86,29 @@ def list_active(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -97,6 +132,8 @@ def list_active(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_active_params.FollowingListActiveParams,
),
@@ -112,6 +149,8 @@ def list_all(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -121,7 +160,16 @@ def list_all(
) -> FollowingListAllResponse:
"""Get a paginated list of followings for an Account.
- Newest followings are first.
+ By default OnlyFans returns
+ this list newest-first, sorted by `subscribedByData.subscribeAt` descending. The
+ expired list does not share this order, so do not assume it applies there. Pass
+ `sort` (optionally with `sortDirection`) to reorder the list — see the parameter
+ description for the caveat that OnlyFans persists the chosen order account-wide.
+ An empty page is not the end of the list: OnlyFans applies `offset` to the whole
+ following collection before filtering it down to the requested list, so a page
+ can come back empty while more results follow. Keep following
+ `_pagination.next_page` until it is `null` instead of stopping at the first
+ empty page.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -131,6 +179,29 @@ def list_all(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -154,6 +225,8 @@ def list_all(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_all_params.FollowingListAllParams,
),
@@ -169,6 +242,8 @@ def list_expired(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -178,8 +253,24 @@ def list_expired(
) -> FollowingListExpiredResponse:
"""Get a paginated list of expired followings for an Account.
- Newest followings are
- first.
+ This list has no
+ order guarantee. Unlike the all and active lists, it is sorted by neither
+ `subscribedByData.subscribeAt` nor `subscribedByData.expiredAt`. To poll for new
+ expirations, page through the full list each cycle (`limit=50`, follow
+ `_pagination.next_page` until it is null) and diff it against your own store
+ using `subscribedByData.expiredAt`. Do NOT stop early at the first entry you
+ have already seen, as that can silently skip real expirations. An empty page is
+ not the end of the list either: OnlyFans applies `offset` to the whole following
+ collection and only then filters that window down to expired subscriptions, so
+ early pages can come back empty while hundreds of expired rows still follow.
+ Keep following `_pagination.next_page` until it is `null` instead of stopping at
+ the first empty page. Pass `sort=expire_date` (optionally with `sortDirection`)
+ to get a deterministic order instead — see the parameter description for the
+ caveat that OnlyFans persists the chosen order account-wide. Ordering by expiry
+ descending puts the still-active subscriptions first and moves the expired rows
+ to the tail of the collection, so prefer `sortDirection=asc` or
+ `sort=is_expired` for expired-first results; for that reason `sort=expire_date`
+ defaults to `asc` on this list when no `sortDirection` is given.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -189,6 +280,29 @@ def list_expired(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -212,6 +326,8 @@ def list_expired(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_expired_params.FollowingListExpiredParams,
),
@@ -250,6 +366,8 @@ async def list_active(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -259,7 +377,16 @@ async def list_active(
) -> FollowingListActiveResponse:
"""Get a paginated list of followings for an Account.
- Newest followings are first.
+ By default OnlyFans returns
+ this list newest-first, sorted by `subscribedByData.subscribeAt` descending. The
+ expired list does not share this order, so do not assume it applies there. Pass
+ `sort` (optionally with `sortDirection`) to reorder the list — see the parameter
+ description for the caveat that OnlyFans persists the chosen order account-wide.
+ An empty page is not the end of the list: OnlyFans applies `offset` to the whole
+ following collection before filtering it down to the requested list, so a page
+ can come back empty while more results follow. Keep following
+ `_pagination.next_page` until it is `null` instead of stopping at the first
+ empty page.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -269,6 +396,29 @@ async def list_active(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -292,6 +442,8 @@ async def list_active(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_active_params.FollowingListActiveParams,
),
@@ -307,6 +459,8 @@ async def list_all(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -316,7 +470,16 @@ async def list_all(
) -> FollowingListAllResponse:
"""Get a paginated list of followings for an Account.
- Newest followings are first.
+ By default OnlyFans returns
+ this list newest-first, sorted by `subscribedByData.subscribeAt` descending. The
+ expired list does not share this order, so do not assume it applies there. Pass
+ `sort` (optionally with `sortDirection`) to reorder the list — see the parameter
+ description for the caveat that OnlyFans persists the chosen order account-wide.
+ An empty page is not the end of the list: OnlyFans applies `offset` to the whole
+ following collection before filtering it down to the requested list, so a page
+ can come back empty while more results follow. Keep following
+ `_pagination.next_page` until it is `null` instead of stopping at the first
+ empty page.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -326,6 +489,29 @@ async def list_all(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -349,6 +535,8 @@ async def list_all(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_all_params.FollowingListAllParams,
),
@@ -364,6 +552,8 @@ async def list_expired(
limit: int | Omit = omit,
offset: int | Omit = omit,
query: Optional[str] | Omit = omit,
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]] | Omit = omit,
+ sort_direction: Optional[Literal["asc", "desc"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -373,8 +563,24 @@ async def list_expired(
) -> FollowingListExpiredResponse:
"""Get a paginated list of expired followings for an Account.
- Newest followings are
- first.
+ This list has no
+ order guarantee. Unlike the all and active lists, it is sorted by neither
+ `subscribedByData.subscribeAt` nor `subscribedByData.expiredAt`. To poll for new
+ expirations, page through the full list each cycle (`limit=50`, follow
+ `_pagination.next_page` until it is null) and diff it against your own store
+ using `subscribedByData.expiredAt`. Do NOT stop early at the first entry you
+ have already seen, as that can silently skip real expirations. An empty page is
+ not the end of the list either: OnlyFans applies `offset` to the whole following
+ collection and only then filters that window down to expired subscriptions, so
+ early pages can come back empty while hundreds of expired rows still follow.
+ Keep following `_pagination.next_page` until it is `null` instead of stopping at
+ the first empty page. Pass `sort=expire_date` (optionally with `sortDirection`)
+ to get a deterministic order instead — see the parameter description for the
+ caveat that OnlyFans persists the chosen order account-wide. Ordering by expiry
+ descending puts the still-active subscriptions first and moves the expired rows
+ to the tail of the collection, so prefer `sortDirection=asc` or
+ `sort=is_expired` for expired-first results; for that reason `sort=expire_date`
+ defaults to `asc` on this list when no `sortDirection` is given.
Args:
limit: Number of followings to return (1-50). Must be at least 1. Must not be greater
@@ -384,6 +590,29 @@ async def list_expired(
query: Search within following name/username.
+ sort: Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+
+ sort_direction: Direction for `sort`: `desc` (default) or `asc`. Requires `sort` to be set.
+ Exception: `sort=expire_date` on the expired list defaults to `asc`, because
+ `desc` moves the expired rows to the tail of the underlying collection and
+ leaves the early pages empty. Passing `sortDirection` explicitly always wins.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -407,6 +636,8 @@ async def list_expired(
"limit": limit,
"offset": offset,
"query": query,
+ "sort": sort,
+ "sort_direction": sort_direction,
},
following_list_expired_params.FollowingListExpiredParams,
),
diff --git a/src/onlyfansapi/resources/link_tags.py b/src/onlyfansapi/resources/link_tags.py
index 75f22c84..46d57c1c 100644
--- a/src/onlyfansapi/resources/link_tags.py
+++ b/src/onlyfansapi/resources/link_tags.py
@@ -24,7 +24,7 @@
class LinkTagsResource(SyncAPIResource):
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
@cached_property
def with_raw_response(self) -> LinkTagsResourceWithRawResponse:
@@ -48,7 +48,7 @@ def with_streaming_response(self) -> LinkTagsResourceWithStreamingResponse:
def list(
self,
*,
- type: Literal["trial_links", "tracking_links"] | Omit = omit,
+ type: Literal["trial_links", "tracking_links", "smart_links"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -57,11 +57,11 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> LinkTagListResponse:
"""
- Get all existing tags that have been used on free trial links and/or tracking
- links for this account. This is a free endpoint.
+ Get all existing tags that have been used on free trial links, tracking links,
+ and/or Smart Links for this account. This is a free endpoint.
Args:
- type: Filter by link type. If not provided, returns tags for both types.
+ type: Filter by link type. If not provided, returns tags for all types.
extra_headers: Send extra headers
@@ -85,7 +85,7 @@ def list(
class AsyncLinkTagsResource(AsyncAPIResource):
- """APIs for managing tags on free trial links and tracking links"""
+ """APIs for managing tags on free trial links, tracking links, and Smart Links"""
@cached_property
def with_raw_response(self) -> AsyncLinkTagsResourceWithRawResponse:
@@ -109,7 +109,7 @@ def with_streaming_response(self) -> AsyncLinkTagsResourceWithStreamingResponse:
async def list(
self,
*,
- type: Literal["trial_links", "tracking_links"] | Omit = omit,
+ type: Literal["trial_links", "tracking_links", "smart_links"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -118,11 +118,11 @@ async def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> LinkTagListResponse:
"""
- Get all existing tags that have been used on free trial links and/or tracking
- links for this account. This is a free endpoint.
+ Get all existing tags that have been used on free trial links, tracking links,
+ and/or Smart Links for this account. This is a free endpoint.
Args:
- type: Filter by link type. If not provided, returns tags for both types.
+ type: Filter by link type. If not provided, returns tags for all types.
extra_headers: Send extra headers
diff --git a/src/onlyfansapi/resources/mass_messaging.py b/src/onlyfansapi/resources/mass_messaging.py
index 417fc523..03fb38e4 100644
--- a/src/onlyfansapi/resources/mass_messaging.py
+++ b/src/onlyfansapi/resources/mass_messaging.py
@@ -3,6 +3,7 @@
from __future__ import annotations
from typing import Iterable
+from typing_extensions import Literal
import httpx
@@ -61,7 +62,8 @@ def retrieve(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingRetrieveResponse:
"""
- Get the content of a mass message.
+ Get the content and settings of a mass message, including a message scheduled
+ for later.
Args:
extra_headers: Send extra headers
@@ -90,11 +92,12 @@ def update(
*,
account: str,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: SequenceNotStr[str] | Omit = omit,
previews: SequenceNotStr[str] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
scheduled_date: str | Omit = omit,
user_ids: SequenceNotStr[str] | Omit = omit,
user_lists: SequenceNotStr[str] | Omit = omit,
@@ -106,11 +109,17 @@ def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingUpdateResponse:
"""
- Update a mass message.
+ Update the content, recipients, media, price, or scheduled send time of an
+ existing mass message.
Args:
text: The message text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
endpoints (`/giphy/trending`, `/giphy/search`).
@@ -123,7 +132,7 @@ def update(
not 0). Will be shown if `price` is provided. All `previews` values must also
exist in the `mediaFiles` array.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
scheduled_date: Schedule the chat message in the future (UTC timezone).
@@ -149,6 +158,7 @@ def update(
body=maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"giphy_id": giphy_id,
"locked_text": locked_text,
"media_files": media_files,
@@ -177,8 +187,10 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingListResponse:
- """
- List the pending or recently sent mass messages in the message queue.
+ """List pending, scheduled, and recently sent mass messages.
+
+ Use an item ID to
+ retrieve, update, reschedule, delete, or unsend the message.
Args:
extra_headers: Send extra headers
@@ -256,8 +268,8 @@ def retrieve_overview(
Get an overview of mass messages, showing the send count and view count.
Args:
- end_date: The latest mass message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest mass message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of mass messages to return (default = 10)
@@ -300,12 +312,13 @@ def send(
account: str,
*,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
excluded_lists: SequenceNotStr[str] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: Iterable[object] | Omit = omit,
previews: Iterable[object] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
rf_guest: str | Omit = omit,
rf_partner: str | Omit = omit,
rf_tag: str | Omit = omit,
@@ -329,6 +342,11 @@ def send(
Args:
text: The message text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
excluded_lists: Array of user list IDs that the mass message will NOT be sent to.
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
@@ -343,7 +361,7 @@ def send(
referencing uploaded files in `mediaFiles`. Will be shown if `price` is
provided.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
rf_guest: Array of OnlyFans Release Form Guest IDs to tag in your mass message
@@ -375,6 +393,7 @@ def send(
body=maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"excluded_lists": excluded_lists,
"giphy_id": giphy_id,
"locked_text": locked_text,
@@ -431,7 +450,8 @@ async def retrieve(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingRetrieveResponse:
"""
- Get the content of a mass message.
+ Get the content and settings of a mass message, including a message scheduled
+ for later.
Args:
extra_headers: Send extra headers
@@ -460,11 +480,12 @@ async def update(
*,
account: str,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: SequenceNotStr[str] | Omit = omit,
previews: SequenceNotStr[str] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
scheduled_date: str | Omit = omit,
user_ids: SequenceNotStr[str] | Omit = omit,
user_lists: SequenceNotStr[str] | Omit = omit,
@@ -476,11 +497,17 @@ async def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingUpdateResponse:
"""
- Update a mass message.
+ Update the content, recipients, media, price, or scheduled send time of an
+ existing mass message.
Args:
text: The message text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
endpoints (`/giphy/trending`, `/giphy/search`).
@@ -493,7 +520,7 @@ async def update(
not 0). Will be shown if `price` is provided. All `previews` values must also
exist in the `mediaFiles` array.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
scheduled_date: Schedule the chat message in the future (UTC timezone).
@@ -519,6 +546,7 @@ async def update(
body=await async_maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"giphy_id": giphy_id,
"locked_text": locked_text,
"media_files": media_files,
@@ -547,8 +575,10 @@ async def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MassMessagingListResponse:
- """
- List the pending or recently sent mass messages in the message queue.
+ """List pending, scheduled, and recently sent mass messages.
+
+ Use an item ID to
+ retrieve, update, reschedule, delete, or unsend the message.
Args:
extra_headers: Send extra headers
@@ -626,8 +656,8 @@ async def retrieve_overview(
Get an overview of mass messages, showing the send count and view count.
Args:
- end_date: The latest mass message to retrieve. Keep empty to get all. MUST BE DATE AFTER
- `startDate`. This is also used for pagination.
+ end_date: The latest mass message to retrieve. Keep empty to get all. It must be after
+ `startDate` and is also used for pagination.
limit: Number of mass messages to return (default = 10)
@@ -670,12 +700,13 @@ async def send(
account: str,
*,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
excluded_lists: SequenceNotStr[str] | Omit = omit,
giphy_id: str | Omit = omit,
locked_text: bool | Omit = omit,
media_files: Iterable[object] | Omit = omit,
previews: Iterable[object] | Omit = omit,
- price: int | Omit = omit,
+ price: float | Omit = omit,
rf_guest: str | Omit = omit,
rf_partner: str | Omit = omit,
rf_tag: str | Omit = omit,
@@ -699,6 +730,11 @@ async def send(
Args:
text: The message text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
excluded_lists: Array of user list IDs that the mass message will NOT be sent to.
giphy_id: The ID of the Giphy GIF to attach to the message. Get IDs from the Giphy listing
@@ -713,7 +749,7 @@ async def send(
referencing uploaded files in `mediaFiles`. Will be shown if `price` is
provided.
- price: Price for paid content (0 or between 3-200). In case this is not zero,
+ price: Price for paid content in USD (0 or between 3-200). In case this is not zero,
**mediaFiles** is required
rf_guest: Array of OnlyFans Release Form Guest IDs to tag in your mass message
@@ -745,6 +781,7 @@ async def send(
body=await async_maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"excluded_lists": excluded_lists,
"giphy_id": giphy_id,
"locked_text": locked_text,
diff --git a/src/onlyfansapi/resources/media/media.py b/src/onlyfansapi/resources/media/media.py
index cc9894ea..e51a8637 100644
--- a/src/onlyfansapi/resources/media/media.py
+++ b/src/onlyfansapi/resources/media/media.py
@@ -17,7 +17,7 @@
AsyncUploadsResourceWithStreamingResponse,
)
from ..._files import deepcopy_with_paths
-from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given
from ..._utils import extract_files, path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
@@ -81,14 +81,15 @@ def download(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> str:
+ ) -> None:
"""Downloads a file directly from a `https://cdn*.onlyfans.com/*` URL.
When the
file is already cached on our CDN, this endpoint returns a `302` redirect to a
`https://cdn.fansapi.com/*` URL. Most HTTP clients follow redirects
- automatically (`curl` requires `-L`). Otherwise, the file is streamed through
- our proxies and queued for caching.
+ automatically (`curl` requires `-L`). Otherwise, the file is redirected to
+ `dl.fansapi.com`, which streams it through the account proxy and reports billing
+ back to the API.
Args:
extra_headers: Send extra headers
@@ -103,13 +104,13 @@ def download(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not cdn_url:
raise ValueError(f"Expected a non-empty value for `cdn_url` but received {cdn_url!r}")
- extra_headers = {"Accept": "text/plain", **(extra_headers or {})}
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._get(
path_template("/api/{account}/media/download/{cdn_url}", account=account, cdn_url=cdn_url),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=str,
+ cast_to=NoneType,
)
def scrape(
@@ -199,7 +200,9 @@ def upload(
Args:
async_: Set to `true` to process uploads in the background. Returns a `polling_url` to
- check status. Recommended for large files.
+ check status. Recommended for large files. Instead of polling, you can subscribe
+ to the `media_uploads.completed` and `media_uploads.failed` webhook events —
+ they only fire for async uploads.
file:
The file to upload. Required if `file_url` is not provided. Maximum file size:
@@ -285,14 +288,15 @@ async def download(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> str:
+ ) -> None:
"""Downloads a file directly from a `https://cdn*.onlyfans.com/*` URL.
When the
file is already cached on our CDN, this endpoint returns a `302` redirect to a
`https://cdn.fansapi.com/*` URL. Most HTTP clients follow redirects
- automatically (`curl` requires `-L`). Otherwise, the file is streamed through
- our proxies and queued for caching.
+ automatically (`curl` requires `-L`). Otherwise, the file is redirected to
+ `dl.fansapi.com`, which streams it through the account proxy and reports billing
+ back to the API.
Args:
extra_headers: Send extra headers
@@ -307,13 +311,13 @@ async def download(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not cdn_url:
raise ValueError(f"Expected a non-empty value for `cdn_url` but received {cdn_url!r}")
- extra_headers = {"Accept": "text/plain", **(extra_headers or {})}
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._get(
path_template("/api/{account}/media/download/{cdn_url}", account=account, cdn_url=cdn_url),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=str,
+ cast_to=NoneType,
)
async def scrape(
@@ -403,7 +407,9 @@ async def upload(
Args:
async_: Set to `true` to process uploads in the background. Returns a `polling_url` to
- check status. Recommended for large files.
+ check status. Recommended for large files. Instead of polling, you can subscribe
+ to the `media_uploads.completed` and `media_uploads.failed` webhook events —
+ they only fire for async uploads.
file:
The file to upload. Required if `file_url` is not provided. Maximum file size:
diff --git a/src/onlyfansapi/resources/media/uploads.py b/src/onlyfansapi/resources/media/uploads.py
index a2b61077..57f32de3 100644
--- a/src/onlyfansapi/resources/media/uploads.py
+++ b/src/onlyfansapi/resources/media/uploads.py
@@ -66,6 +66,11 @@ def get_status(
- `completed` — Upload finished, `media` and `credits_used` are included
- `failed` — Upload failed, `error` is included
+ Instead of polling, you can subscribe to the `media_uploads.completed` and
+ `media_uploads.failed` webhook events. They carry the same fields as this
+ endpoint and are only sent for async (`async=true`) uploads — synchronous
+ uploads return their result directly.
+
Args:
extra_headers: Send extra headers
@@ -137,6 +142,11 @@ async def get_status(
- `completed` — Upload finished, `media` and `credits_used` are included
- `failed` — Upload failed, `error` is included
+ Instead of polling, you can subscribe to the `media_uploads.completed` and
+ `media_uploads.failed` webhook events. They carry the same fields as this
+ endpoint and are only sent for async (`async=true`) uploads — synchronous
+ uploads return their result directly.
+
Args:
extra_headers: Send extra headers
diff --git a/src/onlyfansapi/resources/media/vault/lists/lists.py b/src/onlyfansapi/resources/media/vault/lists/lists.py
index f326e94e..5274387f 100644
--- a/src/onlyfansapi/resources/media/vault/lists/lists.py
+++ b/src/onlyfansapi/resources/media/vault/lists/lists.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+from typing import Any, cast
+
import httpx
from .media import (
@@ -23,7 +25,7 @@
async_to_streamed_response_wrapper,
)
from ....._base_client import make_request_options
-from .....types.media.vault import list_list_params, list_create_params
+from .....types.media.vault import list_list_params, list_create_params, list_update_params
from .....types.media.vault.list_list_response import ListListResponse
from .....types.media.vault.list_create_response import ListCreateResponse
from .....types.media.vault.list_delete_response import ListDeleteResponse
@@ -135,6 +137,7 @@ def update(
list_id: str,
*,
account: str,
+ name: str,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -142,10 +145,13 @@ def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ListUpdateResponse:
- """
- Rename a Vault list.
+ """Rename a Vault list.
Args:
+ name: The new name for the vault list.
+
+ Must not be greater than 255 characters.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -160,6 +166,7 @@ def update(
raise ValueError(f"Expected a non-empty value for `list_id` but received {list_id!r}")
return self._put(
path_template("/api/{account}/media/vault/lists/{list_id}", account=account, list_id=list_id),
+ body=maybe_transform({"name": name}, list_update_params.ListUpdateParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -170,6 +177,7 @@ def list(
self,
account: str,
*,
+ lightweight: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
query: str | Omit = omit,
@@ -183,7 +191,25 @@ def list(
"""
List your Vault lists (categories).
+ Every response carries an `ETag` computed over the `data` payload. Send it back
+ as `If-None-Match` on your next call and you will get a `304 Not Modified` with
+ an empty body when nothing changed, so you can keep serving your cached copy
+ instead of re-parsing the full list. Credits are debited either way — we still
+ have to ask OnlyFans for the current state to know whether it changed.
+
+ The `ETag` covers `data` only, never `_meta` — your credits balance changes on
+ every call, so including it would mean the `ETag` never matches. Because a `304`
+ has no body, it also has no `_meta`: read the current credits and rate-limit
+ counters from the `X-OFAPI-Credits-Used`, `X-OFAPI-Credits-Balance`,
+ `X-Rate-Limit-Limit-Minute` and `X-Rate-Limit-Remaining-Minute` response
+ headers, which are sent on `304` responses too. The `_meta` inside a body you
+ cached earlier is stale by definition.
+
Args:
+ lightweight: Set to `true` to return only `id`, `name`, `type`, `canUpdate` and a rolled-up
+ `mediaCount` per list, dropping the `medias` previews. Much smaller payload —
+ ideal for rendering a folder picker. Default: `false`
+
limit: Number of media to return per page. Default: `24`
offset: The offset used for pagination. Default `0`
@@ -200,23 +226,27 @@ def list(
"""
if not account:
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
- return self._get(
- path_template("/api/{account}/media/vault/lists", account=account),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "limit": limit,
- "offset": offset,
- "query": query,
- },
- list_list_params.ListListParams,
+ return cast(
+ ListListResponse,
+ self._get(
+ path_template("/api/{account}/media/vault/lists", account=account),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "lightweight": lightweight,
+ "limit": limit,
+ "offset": offset,
+ "query": query,
+ },
+ list_list_params.ListListParams,
+ ),
),
+ cast_to=cast(Any, ListListResponse), # Union types cannot be passed in as arguments in the type system
),
- cast_to=ListListResponse,
)
def delete(
@@ -358,6 +388,7 @@ async def update(
list_id: str,
*,
account: str,
+ name: str,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -365,10 +396,13 @@ async def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ListUpdateResponse:
- """
- Rename a Vault list.
+ """Rename a Vault list.
Args:
+ name: The new name for the vault list.
+
+ Must not be greater than 255 characters.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -383,6 +417,7 @@ async def update(
raise ValueError(f"Expected a non-empty value for `list_id` but received {list_id!r}")
return await self._put(
path_template("/api/{account}/media/vault/lists/{list_id}", account=account, list_id=list_id),
+ body=await async_maybe_transform({"name": name}, list_update_params.ListUpdateParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -393,6 +428,7 @@ async def list(
self,
account: str,
*,
+ lightweight: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
query: str | Omit = omit,
@@ -406,7 +442,25 @@ async def list(
"""
List your Vault lists (categories).
+ Every response carries an `ETag` computed over the `data` payload. Send it back
+ as `If-None-Match` on your next call and you will get a `304 Not Modified` with
+ an empty body when nothing changed, so you can keep serving your cached copy
+ instead of re-parsing the full list. Credits are debited either way — we still
+ have to ask OnlyFans for the current state to know whether it changed.
+
+ The `ETag` covers `data` only, never `_meta` — your credits balance changes on
+ every call, so including it would mean the `ETag` never matches. Because a `304`
+ has no body, it also has no `_meta`: read the current credits and rate-limit
+ counters from the `X-OFAPI-Credits-Used`, `X-OFAPI-Credits-Balance`,
+ `X-Rate-Limit-Limit-Minute` and `X-Rate-Limit-Remaining-Minute` response
+ headers, which are sent on `304` responses too. The `_meta` inside a body you
+ cached earlier is stale by definition.
+
Args:
+ lightweight: Set to `true` to return only `id`, `name`, `type`, `canUpdate` and a rolled-up
+ `mediaCount` per list, dropping the `medias` previews. Much smaller payload —
+ ideal for rendering a folder picker. Default: `false`
+
limit: Number of media to return per page. Default: `24`
offset: The offset used for pagination. Default `0`
@@ -423,23 +477,27 @@ async def list(
"""
if not account:
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
- return await self._get(
- path_template("/api/{account}/media/vault/lists", account=account),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "limit": limit,
- "offset": offset,
- "query": query,
- },
- list_list_params.ListListParams,
+ return cast(
+ ListListResponse,
+ await self._get(
+ path_template("/api/{account}/media/vault/lists", account=account),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "lightweight": lightweight,
+ "limit": limit,
+ "offset": offset,
+ "query": query,
+ },
+ list_list_params.ListListParams,
+ ),
),
+ cast_to=cast(Any, ListListResponse), # Union types cannot be passed in as arguments in the type system
),
- cast_to=ListListResponse,
)
async def delete(
diff --git a/src/onlyfansapi/resources/media/vault/vault.py b/src/onlyfansapi/resources/media/vault/vault.py
index ef518546..2a02fff7 100644
--- a/src/onlyfansapi/resources/media/vault/vault.py
+++ b/src/onlyfansapi/resources/media/vault/vault.py
@@ -232,7 +232,9 @@ def upload(
Args:
async_: Set to `true` to process uploads in the background. Returns a `polling_url` to
- check status. Recommended for large files.
+ check status. Recommended for large files. Instead of polling, you can subscribe
+ to the `media_uploads.completed` and `media_uploads.failed` webhook events —
+ they only fire for async uploads.
file:
The file to upload. Required if `file_url` is not provided. Maximum file size:
@@ -461,7 +463,9 @@ async def upload(
Args:
async_: Set to `true` to process uploads in the background. Returns a `polling_url` to
- check status. Recommended for large files.
+ check status. Recommended for large files. Instead of polling, you can subscribe
+ to the `media_uploads.completed` and `media_uploads.failed` webhook events —
+ they only fire for async uploads.
file:
The file to upload. Required if `file_url` is not provided. Maximum file size:
diff --git a/src/onlyfansapi/resources/messages.py b/src/onlyfansapi/resources/messages.py
deleted file mode 100644
index 414fe8d4..00000000
--- a/src/onlyfansapi/resources/messages.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import httpx
-
-from ..types import message_attach_tags_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import path_template, maybe_transform, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-from ..types.message_attach_tags_response import MessageAttachTagsResponse
-
-__all__ = ["MessagesResource", "AsyncMessagesResource"]
-
-
-class MessagesResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> MessagesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onlyfansapi/onlyfansapi-python#accessing-raw-response-data-eg-headers
- """
- return MessagesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> MessagesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onlyfansapi/onlyfansapi-python#with_streaming_response
- """
- return MessagesResourceWithStreamingResponse(self)
-
- def attach_tags(
- self,
- message_id: str,
- *,
- account: str,
- rf_guest: str | Omit = omit,
- rf_partner: str | Omit = omit,
- rf_tag: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> MessageAttachTagsResponse:
- """Attach Tags (Release Forms) to a message that has already been sent.
-
- Please
- note, that this is a "sync" operation - for example, if you provide empty
- `rfTag` it will remove all existing tags already attached to the message.
-
- Args:
- rf_guest: Array of OnlyFans Release Form Guest IDs to tag in your message
-
- rf_partner: Array of OnlyFans Release Form Partners IDs to tag in your message
-
- rf_tag: Array of OnlyFans Creator User IDs to tag in your message
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not account:
- raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
- if not message_id:
- raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}")
- return self._post(
- path_template("/api/{account}/messages/{message_id}/attach-tags", account=account, message_id=message_id),
- body=maybe_transform(
- {
- "rf_guest": rf_guest,
- "rf_partner": rf_partner,
- "rf_tag": rf_tag,
- },
- message_attach_tags_params.MessageAttachTagsParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=MessageAttachTagsResponse,
- )
-
-
-class AsyncMessagesResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncMessagesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onlyfansapi/onlyfansapi-python#accessing-raw-response-data-eg-headers
- """
- return AsyncMessagesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncMessagesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onlyfansapi/onlyfansapi-python#with_streaming_response
- """
- return AsyncMessagesResourceWithStreamingResponse(self)
-
- async def attach_tags(
- self,
- message_id: str,
- *,
- account: str,
- rf_guest: str | Omit = omit,
- rf_partner: str | Omit = omit,
- rf_tag: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> MessageAttachTagsResponse:
- """Attach Tags (Release Forms) to a message that has already been sent.
-
- Please
- note, that this is a "sync" operation - for example, if you provide empty
- `rfTag` it will remove all existing tags already attached to the message.
-
- Args:
- rf_guest: Array of OnlyFans Release Form Guest IDs to tag in your message
-
- rf_partner: Array of OnlyFans Release Form Partners IDs to tag in your message
-
- rf_tag: Array of OnlyFans Creator User IDs to tag in your message
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not account:
- raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
- if not message_id:
- raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}")
- return await self._post(
- path_template("/api/{account}/messages/{message_id}/attach-tags", account=account, message_id=message_id),
- body=await async_maybe_transform(
- {
- "rf_guest": rf_guest,
- "rf_partner": rf_partner,
- "rf_tag": rf_tag,
- },
- message_attach_tags_params.MessageAttachTagsParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=MessageAttachTagsResponse,
- )
-
-
-class MessagesResourceWithRawResponse:
- def __init__(self, messages: MessagesResource) -> None:
- self._messages = messages
-
- self.attach_tags = to_raw_response_wrapper(
- messages.attach_tags,
- )
-
-
-class AsyncMessagesResourceWithRawResponse:
- def __init__(self, messages: AsyncMessagesResource) -> None:
- self._messages = messages
-
- self.attach_tags = async_to_raw_response_wrapper(
- messages.attach_tags,
- )
-
-
-class MessagesResourceWithStreamingResponse:
- def __init__(self, messages: MessagesResource) -> None:
- self._messages = messages
-
- self.attach_tags = to_streamed_response_wrapper(
- messages.attach_tags,
- )
-
-
-class AsyncMessagesResourceWithStreamingResponse:
- def __init__(self, messages: AsyncMessagesResource) -> None:
- self._messages = messages
-
- self.attach_tags = async_to_streamed_response_wrapper(
- messages.attach_tags,
- )
diff --git a/src/onlyfansapi/resources/notifications/notifications.py b/src/onlyfansapi/resources/notifications/notifications.py
index 848f1db1..b05b1e7b 100644
--- a/src/onlyfansapi/resources/notifications/notifications.py
+++ b/src/onlyfansapi/resources/notifications/notifications.py
@@ -98,7 +98,7 @@ def list(
limit: The number of notifications. Default `10`
- skip_users: Whether to skip user details. Default `all`
+ skip_users: Whether to skip user details. Defaults to `all`.
type: Filter notifications by a specific type
@@ -303,7 +303,7 @@ async def list(
limit: The number of notifications. Default `10`
- skip_users: Whether to skip user details. Default `all`
+ skip_users: Whether to skip user details. Defaults to `all`.
type: Filter notifications by a specific type
diff --git a/src/onlyfansapi/resources/posts/posts.py b/src/onlyfansapi/resources/posts/posts.py
index 5bf6dd37..78aeeba1 100644
--- a/src/onlyfansapi/resources/posts/posts.py
+++ b/src/onlyfansapi/resources/posts/posts.py
@@ -90,6 +90,7 @@ def create(
account: str,
*,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
expire_days: int | Omit = omit,
fund_raising_target_amount: int | Omit = omit,
fund_raising_tips_presets: SequenceNotStr[str] | Omit = omit,
@@ -116,6 +117,11 @@ def create(
Args:
text: The post text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the post if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
expire_days: Number of days after which the post will expire. Between 1 and 30 days. Keep
empty for no expiration.
@@ -164,6 +170,7 @@ def create(
body=maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"expire_days": expire_days,
"fund_raising_target_amount": fund_raising_target_amount,
"fund_raising_tips_presets": fund_raising_tips_presets,
@@ -226,6 +233,7 @@ def update(
*,
account: str,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
expire_days: int | Omit = omit,
fund_raising_target_amount: int | Omit = omit,
fund_raising_tips_presets: SequenceNotStr[str] | Omit = omit,
@@ -252,6 +260,11 @@ def update(
Args:
text: The post text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
expire_days: Number of days after which the post will expire. Between 1 and 30 days. Keep
empty for no expiration.
@@ -300,6 +313,7 @@ def update(
body=maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"expire_days": expire_days,
"fund_raising_target_amount": fund_raising_target_amount,
"fund_raising_tips_presets": fund_raising_tips_presets,
@@ -627,6 +641,7 @@ async def create(
account: str,
*,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
expire_days: int | Omit = omit,
fund_raising_target_amount: int | Omit = omit,
fund_raising_tips_presets: SequenceNotStr[str] | Omit = omit,
@@ -653,6 +668,11 @@ async def create(
Args:
text: The post text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the post if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
expire_days: Number of days after which the post will expire. Between 1 and 30 days. Keep
empty for no expiration.
@@ -701,6 +721,7 @@ async def create(
body=await async_maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"expire_days": expire_days,
"fund_raising_target_amount": fund_raising_target_amount,
"fund_raising_tips_presets": fund_raising_tips_presets,
@@ -763,6 +784,7 @@ async def update(
*,
account: str,
text: str,
+ block_banned_words: Literal["strict_ban", "risky", "replace_soften"] | Omit = omit,
expire_days: int | Omit = omit,
fund_raising_target_amount: int | Omit = omit,
fund_raising_tips_presets: SequenceNotStr[str] | Omit = omit,
@@ -789,6 +811,11 @@ async def update(
Args:
text: The post text content
+ block_banned_words: Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+
expire_days: Number of days after which the post will expire. Between 1 and 30 days. Keep
empty for no expiration.
@@ -837,6 +864,7 @@ async def update(
body=await async_maybe_transform(
{
"text": text,
+ "block_banned_words": block_banned_words,
"expire_days": expire_days,
"fund_raising_target_amount": fund_raising_target_amount,
"fund_raising_tips_presets": fund_raising_tips_presets,
diff --git a/src/onlyfansapi/resources/queue.py b/src/onlyfansapi/resources/queue.py
index 68a2fa71..20a96cca 100644
--- a/src/onlyfansapi/resources/queue.py
+++ b/src/onlyfansapi/resources/queue.py
@@ -2,10 +2,13 @@
from __future__ import annotations
+from typing import List
+from typing_extensions import Literal
+
import httpx
from ..types import queue_list_params, queue_count_params
-from .._types import Body, Query, Headers, NotGiven, not_given
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -47,10 +50,11 @@ def list(
self,
account: str,
*,
- limit: int,
publish_date_end: str,
publish_date_start: str,
timezone: str,
+ limit: int | Omit = omit,
+ type: List[Literal["chat", "post"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -58,18 +62,24 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> QueueListResponse:
- """
- List posts and messages in the queue.
+ """List scheduled posts and mass messages for a date range.
+
+ Use the type filter to
+ return only posts, messages, or both.
Args:
- limit: Maximum number of queue items to return (default = 20)
+ publish_date_end: Latest publish date to return. Must be a valid date. Must be a valid date. Must
+ be a date after or equal to publishDateStart.
- publish_date_end: Latest publish date to return
+ publish_date_start: Earliest publish date to return (must be at least today). Must be a valid date.
+ Must be a valid date. Must be a date after or equal to today.
- publish_date_start: Earliest publish date to return (must be at least today)
+ timezone: Timezone of the provided dates.
+ [View available timezone values](https://www.php.net/manual/en/timezones.php).
+ Must be a valid time zone, such as Africa/Accra.
- timezone: Time timezone of the provided dates.
- [View available timezone values](https://www.php.net/manual/en/timezones.php)
+ limit: Maximum number of queue items to return (default 20). Must be at least 1. Must
+ not be greater than 100.
extra_headers: Send extra headers
@@ -90,10 +100,11 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "limit": limit,
"publish_date_end": publish_date_end,
"publish_date_start": publish_date_start,
"timezone": timezone,
+ "limit": limit,
+ "type": type,
},
queue_list_params.QueueListParams,
),
@@ -218,10 +229,11 @@ async def list(
self,
account: str,
*,
- limit: int,
publish_date_end: str,
publish_date_start: str,
timezone: str,
+ limit: int | Omit = omit,
+ type: List[Literal["chat", "post"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -229,18 +241,24 @@ async def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> QueueListResponse:
- """
- List posts and messages in the queue.
+ """List scheduled posts and mass messages for a date range.
+
+ Use the type filter to
+ return only posts, messages, or both.
Args:
- limit: Maximum number of queue items to return (default = 20)
+ publish_date_end: Latest publish date to return. Must be a valid date. Must be a valid date. Must
+ be a date after or equal to publishDateStart.
- publish_date_end: Latest publish date to return
+ publish_date_start: Earliest publish date to return (must be at least today). Must be a valid date.
+ Must be a valid date. Must be a date after or equal to today.
- publish_date_start: Earliest publish date to return (must be at least today)
+ timezone: Timezone of the provided dates.
+ [View available timezone values](https://www.php.net/manual/en/timezones.php).
+ Must be a valid time zone, such as Africa/Accra.
- timezone: Time timezone of the provided dates.
- [View available timezone values](https://www.php.net/manual/en/timezones.php)
+ limit: Maximum number of queue items to return (default 20). Must be at least 1. Must
+ not be greater than 100.
extra_headers: Send extra headers
@@ -261,10 +279,11 @@ async def list(
timeout=timeout,
query=await async_maybe_transform(
{
- "limit": limit,
"publish_date_end": publish_date_end,
"publish_date_start": publish_date_start,
"timezone": timezone,
+ "limit": limit,
+ "type": type,
},
queue_list_params.QueueListParams,
),
diff --git a/src/onlyfansapi/resources/release_forms.py b/src/onlyfansapi/resources/release_forms.py
index 42af3a5c..a927293d 100644
--- a/src/onlyfansapi/resources/release_forms.py
+++ b/src/onlyfansapi/resources/release_forms.py
@@ -151,7 +151,8 @@ def list_taggable_users(
These are
verified creators who have signed release forms to appear in your content. Use
- `offset` and `limit` for pagination.
+ `offset` and `limit` for pagination, following `_pagination.next_page` until it
+ is `null`.
Args:
filter: Filter users by type: `all` or `pending`.
@@ -321,7 +322,8 @@ async def list_taggable_users(
These are
verified creators who have signed release forms to appear in your content. Use
- `offset` and `limit` for pagination.
+ `offset` and `limit` for pagination, following `_pagination.next_page` until it
+ is `null`.
Args:
filter: Filter users by type: `all` or `pending`.
diff --git a/src/onlyfansapi/resources/shared_tracking_links/shared_tracking_links.py b/src/onlyfansapi/resources/shared_tracking_links/shared_tracking_links.py
index f1ee947b..7dbbf4b8 100644
--- a/src/onlyfansapi/resources/shared_tracking_links/shared_tracking_links.py
+++ b/src/onlyfansapi/resources/shared_tracking_links/shared_tracking_links.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Optional
+from typing_extensions import Literal
import httpx
@@ -69,7 +69,11 @@ def list(
*,
limit: int | Omit = omit,
offset: int | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ sorting_deleted: Literal[0, 1] | Omit = omit,
+ stats: str | Omit = omit,
+ synchronous: bool | Omit = omit,
+ with_deleted: Literal[0, 1] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -83,12 +87,21 @@ def list(
Calls OnlyFans live and syncs to our cache.
Args:
- limit: The number of shared tracking links to return. Default `10`
+ limit: The number of shared tracking links to return. Default `10`. Must be at least 1.
+ Must not be greater than 100.
- offset: The offset used for pagination. Default `0`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- synchronous: Wait for the database sync to finish, instead of running it in the background.
- **Will result in longer response times, use with caution**. Default `false`
+ pagination: Whether pagination metadata is enabled. Default `1`.
+
+ sorting_deleted: Whether deleted links participate in sorting. Default `1`.
+
+ stats: Whether statistics are included. Default `true`. Must not be greater than 10
+ characters.
+
+ synchronous: Wait for the database sync instead of processing it in the background.
+
+ with_deleted: Whether to include deleted shared tracking links. Default `1`.
extra_headers: Send extra headers
@@ -111,7 +124,11 @@ def list(
{
"limit": limit,
"offset": offset,
+ "pagination": pagination,
+ "sorting_deleted": sorting_deleted,
+ "stats": stats,
"synchronous": synchronous,
+ "with_deleted": with_deleted,
},
shared_tracking_link_list_params.SharedTrackingLinkListParams,
),
@@ -198,7 +215,11 @@ async def list(
*,
limit: int | Omit = omit,
offset: int | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ sorting_deleted: Literal[0, 1] | Omit = omit,
+ stats: str | Omit = omit,
+ synchronous: bool | Omit = omit,
+ with_deleted: Literal[0, 1] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -212,12 +233,21 @@ async def list(
Calls OnlyFans live and syncs to our cache.
Args:
- limit: The number of shared tracking links to return. Default `10`
+ limit: The number of shared tracking links to return. Default `10`. Must be at least 1.
+ Must not be greater than 100.
+
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
+
+ pagination: Whether pagination metadata is enabled. Default `1`.
+
+ sorting_deleted: Whether deleted links participate in sorting. Default `1`.
+
+ stats: Whether statistics are included. Default `true`. Must not be greater than 10
+ characters.
- offset: The offset used for pagination. Default `0`
+ synchronous: Wait for the database sync instead of processing it in the background.
- synchronous: Wait for the database sync to finish, instead of running it in the background.
- **Will result in longer response times, use with caution**. Default `false`
+ with_deleted: Whether to include deleted shared tracking links. Default `1`.
extra_headers: Send extra headers
@@ -240,7 +270,11 @@ async def list(
{
"limit": limit,
"offset": offset,
+ "pagination": pagination,
+ "sorting_deleted": sorting_deleted,
+ "stats": stats,
"synchronous": synchronous,
+ "with_deleted": with_deleted,
},
shared_tracking_link_list_params.SharedTrackingLinkListParams,
),
diff --git a/src/onlyfansapi/resources/shared_trial_links/shared_trial_links.py b/src/onlyfansapi/resources/shared_trial_links/shared_trial_links.py
index fb81d012..a5d6319e 100644
--- a/src/onlyfansapi/resources/shared_trial_links/shared_trial_links.py
+++ b/src/onlyfansapi/resources/shared_trial_links/shared_trial_links.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Optional
+from typing_extensions import Literal
import httpx
@@ -71,7 +71,8 @@ def list(
*,
limit: int | Omit = omit,
offset: int | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ synchronous: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -85,12 +86,12 @@ def list(
OnlyFans live and syncs to our cache.
Args:
- limit: The number of shared trial links to return. Default `10`
+ limit: The number of shared trial links to return. Default `10`. Must be at least 1.
+ Must not be greater than 100.
- offset: The offset used for pagination. Default `0`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- synchronous: Wait for the database sync to finish, instead of running it in the background.
- **Will result in longer response times, use with caution**. Default `false`
+ synchronous: Wait for the database sync instead of processing it in the background.
extra_headers: Send extra headers
@@ -113,6 +114,7 @@ def list(
{
"limit": limit,
"offset": offset,
+ "pagination": pagination,
"synchronous": synchronous,
},
shared_trial_link_list_params.SharedTrialLinkListParams,
@@ -202,7 +204,8 @@ async def list(
*,
limit: int | Omit = omit,
offset: int | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ synchronous: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -216,12 +219,12 @@ async def list(
OnlyFans live and syncs to our cache.
Args:
- limit: The number of shared trial links to return. Default `10`
+ limit: The number of shared trial links to return. Default `10`. Must be at least 1.
+ Must not be greater than 100.
- offset: The offset used for pagination. Default `0`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- synchronous: Wait for the database sync to finish, instead of running it in the background.
- **Will result in longer response times, use with caution**. Default `false`
+ synchronous: Wait for the database sync instead of processing it in the background.
extra_headers: Send extra headers
@@ -244,6 +247,7 @@ async def list(
{
"limit": limit,
"offset": offset,
+ "pagination": pagination,
"synchronous": synchronous,
},
shared_trial_link_list_params.SharedTrialLinkListParams,
diff --git a/src/onlyfansapi/resources/smart_link_postbacks.py b/src/onlyfansapi/resources/smart_link_postbacks.py
index 7c10116c..d3301aeb 100644
--- a/src/onlyfansapi/resources/smart_link_postbacks.py
+++ b/src/onlyfansapi/resources/smart_link_postbacks.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Optional
+from typing import Iterable, Optional
from typing_extensions import Literal
import httpx
@@ -56,6 +56,9 @@ def create(
conversion_types: SequenceNotStr[str],
smart_link_scope: Literal["global", "campaign_specific"],
url: str,
+ body: str | Omit = omit,
+ headers: Iterable[smart_link_postback_create_params.Header] | Omit = omit,
+ http_method: Literal["GET", "POST"] | Omit = omit,
smart_link_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -73,8 +76,15 @@ def create(
smart_link_scope: `global` fires for all Smart Links. `campaign_specific` fires only for selected
Smart Links.
- url: The destination URL. Variables such as `{click_id}`, `{fbclid}`, `{gclid}`, and
- `{ttclid}` are replaced when the postback is dispatched.
+ url: The destination URL. Variables such as `{external_click_id}`, `{fbclid}`,
+ `{gclid}`, and `{ttclid}` are replaced when the postback is dispatched.
+
+ body: Optional request body template for POST postbacks. Variables are replaced when
+ the postback is dispatched.
+
+ headers: Optional request headers. Header values may include postback variables.
+
+ http_method: HTTP method used for the postback request. Defaults to `GET` when omitted.
smart_link_ids: Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`.
@@ -93,6 +103,9 @@ def create(
"conversion_types": conversion_types,
"smart_link_scope": smart_link_scope,
"url": url,
+ "body": body,
+ "headers": headers,
+ "http_method": http_method,
"smart_link_ids": smart_link_ids,
},
smart_link_postback_create_params.SmartLinkPostbackCreateParams,
@@ -141,6 +154,9 @@ def update(
conversion_types: SequenceNotStr[str],
smart_link_scope: Literal["global", "campaign_specific"],
url: str,
+ body: str | Omit = omit,
+ headers: Iterable[smart_link_postback_update_params.Header] | Omit = omit,
+ http_method: Literal["GET", "POST"] | Omit = omit,
smart_link_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -159,6 +175,13 @@ def update(
url: The destination URL.
+ body: Optional request body template for POST postbacks. Variables are replaced when
+ the postback is dispatched.
+
+ headers: Optional request headers. Header values may include postback variables.
+
+ http_method: HTTP method used for the postback request. Existing value is kept when omitted.
+
smart_link_ids: Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`.
extra_headers: Send extra headers
@@ -176,6 +199,9 @@ def update(
"conversion_types": conversion_types,
"smart_link_scope": smart_link_scope,
"url": url,
+ "body": body,
+ "headers": headers,
+ "http_method": http_method,
"smart_link_ids": smart_link_ids,
},
smart_link_postback_update_params.SmartLinkPostbackUpdateParams,
@@ -265,6 +291,9 @@ async def create(
conversion_types: SequenceNotStr[str],
smart_link_scope: Literal["global", "campaign_specific"],
url: str,
+ body: str | Omit = omit,
+ headers: Iterable[smart_link_postback_create_params.Header] | Omit = omit,
+ http_method: Literal["GET", "POST"] | Omit = omit,
smart_link_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -282,8 +311,15 @@ async def create(
smart_link_scope: `global` fires for all Smart Links. `campaign_specific` fires only for selected
Smart Links.
- url: The destination URL. Variables such as `{click_id}`, `{fbclid}`, `{gclid}`, and
- `{ttclid}` are replaced when the postback is dispatched.
+ url: The destination URL. Variables such as `{external_click_id}`, `{fbclid}`,
+ `{gclid}`, and `{ttclid}` are replaced when the postback is dispatched.
+
+ body: Optional request body template for POST postbacks. Variables are replaced when
+ the postback is dispatched.
+
+ headers: Optional request headers. Header values may include postback variables.
+
+ http_method: HTTP method used for the postback request. Defaults to `GET` when omitted.
smart_link_ids: Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`.
@@ -302,6 +338,9 @@ async def create(
"conversion_types": conversion_types,
"smart_link_scope": smart_link_scope,
"url": url,
+ "body": body,
+ "headers": headers,
+ "http_method": http_method,
"smart_link_ids": smart_link_ids,
},
smart_link_postback_create_params.SmartLinkPostbackCreateParams,
@@ -350,6 +389,9 @@ async def update(
conversion_types: SequenceNotStr[str],
smart_link_scope: Literal["global", "campaign_specific"],
url: str,
+ body: str | Omit = omit,
+ headers: Iterable[smart_link_postback_update_params.Header] | Omit = omit,
+ http_method: Literal["GET", "POST"] | Omit = omit,
smart_link_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -368,6 +410,13 @@ async def update(
url: The destination URL.
+ body: Optional request body template for POST postbacks. Variables are replaced when
+ the postback is dispatched.
+
+ headers: Optional request headers. Header values may include postback variables.
+
+ http_method: HTTP method used for the postback request. Existing value is kept when omitted.
+
smart_link_ids: Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`.
extra_headers: Send extra headers
@@ -385,6 +434,9 @@ async def update(
"conversion_types": conversion_types,
"smart_link_scope": smart_link_scope,
"url": url,
+ "body": body,
+ "headers": headers,
+ "http_method": http_method,
"smart_link_ids": smart_link_ids,
},
smart_link_postback_update_params.SmartLinkPostbackUpdateParams,
diff --git a/src/onlyfansapi/resources/smart_links.py b/src/onlyfansapi/resources/smart_links.py
index 375f214b..675edf24 100644
--- a/src/onlyfansapi/resources/smart_links.py
+++ b/src/onlyfansapi/resources/smart_links.py
@@ -156,10 +156,11 @@ def list(
self,
*,
account_ids: Optional[str] | Omit = omit,
+ filter: smart_link_list_params.Filter | Omit = omit,
limit: int | Omit = omit,
- meta_pixel_ids: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
offset: int | Omit = omit,
+ pixel_ids: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -176,12 +177,12 @@ def list(
limit: The number of Smart Links to return. Default `50`. Must be at least 1. Must not
be greater than 1000.
- meta_pixel_ids: Comma-separated Meta Pixel IDs to include.
-
name: Filter Smart Links by name. Must not be greater than 255 characters.
offset: The offset used for pagination. Default `0`. Must be at least 0.
+ pixel_ids: Comma-separated ad platform Pixel IDs to include.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -200,10 +201,11 @@ def list(
query=maybe_transform(
{
"account_ids": account_ids,
+ "filter": filter,
"limit": limit,
- "meta_pixel_ids": meta_pixel_ids,
"name": name,
"offset": offset,
+ "pixel_ids": pixel_ids,
},
smart_link_list_params.SmartLinkListParams,
),
@@ -313,7 +315,9 @@ def list_conversions(
self,
smart_link_id: str,
*,
- conversion_type: Literal["new_subscriber", "new_transaction", "message_received", "fan_sent_3_messages"]
+ conversion_type: Literal[
+ "new_subscriber", "new_transaction", "message_received", "fan_sent_1_message", "fan_sent_3_messages"
+ ]
| Omit = omit,
date_end: str | Omit = omit,
date_start: str | Omit = omit,
@@ -394,6 +398,7 @@ def list_fans(
min_revenue_net: float | Omit = omit,
min_tips_net: float | Omit = omit,
offset: int | Omit = omit,
+ previously_subscribed: bool | Omit = omit,
sort: Literal[
"revenue_net",
"-revenue_net",
@@ -405,6 +410,7 @@ def list_fans(
"-converted_at",
]
| Omit = omit,
+ subscribed_using_promo: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -429,8 +435,13 @@ def list_fans(
offset: Offset for pagination. Default `0`
+ previously_subscribed: Optional - Filter to returning subscribers (fans previously subscribed before
+ this subscription)
+
sort: Optional sort field. Default `-revenue_net`
+ subscribed_using_promo: Optional - Filter to fans who subscribed via a promotion/offer
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -456,7 +467,9 @@ def list_fans(
"min_revenue_net": min_revenue_net,
"min_tips_net": min_tips_net,
"offset": offset,
+ "previously_subscribed": previously_subscribed,
"sort": sort,
+ "subscribed_using_promo": subscribed_using_promo,
},
smart_link_list_fans_params.SmartLinkListFansParams,
),
@@ -737,10 +750,11 @@ async def list(
self,
*,
account_ids: Optional[str] | Omit = omit,
+ filter: smart_link_list_params.Filter | Omit = omit,
limit: int | Omit = omit,
- meta_pixel_ids: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
offset: int | Omit = omit,
+ pixel_ids: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -757,12 +771,12 @@ async def list(
limit: The number of Smart Links to return. Default `50`. Must be at least 1. Must not
be greater than 1000.
- meta_pixel_ids: Comma-separated Meta Pixel IDs to include.
-
name: Filter Smart Links by name. Must not be greater than 255 characters.
offset: The offset used for pagination. Default `0`. Must be at least 0.
+ pixel_ids: Comma-separated ad platform Pixel IDs to include.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -781,10 +795,11 @@ async def list(
query=await async_maybe_transform(
{
"account_ids": account_ids,
+ "filter": filter,
"limit": limit,
- "meta_pixel_ids": meta_pixel_ids,
"name": name,
"offset": offset,
+ "pixel_ids": pixel_ids,
},
smart_link_list_params.SmartLinkListParams,
),
@@ -894,7 +909,9 @@ async def list_conversions(
self,
smart_link_id: str,
*,
- conversion_type: Literal["new_subscriber", "new_transaction", "message_received", "fan_sent_3_messages"]
+ conversion_type: Literal[
+ "new_subscriber", "new_transaction", "message_received", "fan_sent_1_message", "fan_sent_3_messages"
+ ]
| Omit = omit,
date_end: str | Omit = omit,
date_start: str | Omit = omit,
@@ -975,6 +992,7 @@ async def list_fans(
min_revenue_net: float | Omit = omit,
min_tips_net: float | Omit = omit,
offset: int | Omit = omit,
+ previously_subscribed: bool | Omit = omit,
sort: Literal[
"revenue_net",
"-revenue_net",
@@ -986,6 +1004,7 @@ async def list_fans(
"-converted_at",
]
| Omit = omit,
+ subscribed_using_promo: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -1010,8 +1029,13 @@ async def list_fans(
offset: Offset for pagination. Default `0`
+ previously_subscribed: Optional - Filter to returning subscribers (fans previously subscribed before
+ this subscription)
+
sort: Optional sort field. Default `-revenue_net`
+ subscribed_using_promo: Optional - Filter to fans who subscribed via a promotion/offer
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1037,7 +1061,9 @@ async def list_fans(
"min_revenue_net": min_revenue_net,
"min_tips_net": min_tips_net,
"offset": offset,
+ "previously_subscribed": previously_subscribed,
"sort": sort,
+ "subscribed_using_promo": subscribed_using_promo,
},
smart_link_list_fans_params.SmartLinkListFansParams,
),
diff --git a/src/onlyfansapi/resources/statistics/reach.py b/src/onlyfansapi/resources/statistics/reach.py
index 4cb448b4..8c2cd5ae 100644
--- a/src/onlyfansapi/resources/statistics/reach.py
+++ b/src/onlyfansapi/resources/statistics/reach.py
@@ -66,7 +66,7 @@ def get_profile_visitors(
Args:
end_date: The end date for the period.
- start_date: The start date for the period
+ start_date: The start date for the period.
filter: Optionally, filter the results by `chart` or `topCountries`. See example
responses.
@@ -154,7 +154,7 @@ async def get_profile_visitors(
Args:
end_date: The end date for the period.
- start_date: The start date for the period
+ start_date: The start date for the period.
filter: Optionally, filter the results by `chart` or `topCountries`. See example
responses.
diff --git a/src/onlyfansapi/resources/statistics/statements.py b/src/onlyfansapi/resources/statistics/statements.py
index 5ee33ad6..5ee8dc65 100644
--- a/src/onlyfansapi/resources/statistics/statements.py
+++ b/src/onlyfansapi/resources/statistics/statements.py
@@ -47,8 +47,8 @@ def get_earnings(
self,
account: str,
*,
+ end_date: str,
start_date: str,
- end_date: str | Omit = omit,
type: Literal["total", "subscribes", "tips", "post", "messages", "stream"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -61,10 +61,10 @@ def get_earnings(
Get the earnings for a given period.
Args:
- start_date: The start date for the period
-
end_date: The end date for the period.
+ start_date: The start date for the period.
+
type: Filter by All / Subscriptions / Tips / Posts / Messages / Streams
extra_headers: Send extra headers
@@ -86,8 +86,8 @@ def get_earnings(
timeout=timeout,
query=maybe_transform(
{
- "start_date": start_date,
"end_date": end_date,
+ "start_date": start_date,
"type": type,
},
statement_get_earnings_params.StatementGetEarningsParams,
@@ -121,8 +121,8 @@ async def get_earnings(
self,
account: str,
*,
+ end_date: str,
start_date: str,
- end_date: str | Omit = omit,
type: Literal["total", "subscribes", "tips", "post", "messages", "stream"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -135,10 +135,10 @@ async def get_earnings(
Get the earnings for a given period.
Args:
- start_date: The start date for the period
-
end_date: The end date for the period.
+ start_date: The start date for the period.
+
type: Filter by All / Subscriptions / Tips / Posts / Messages / Streams
extra_headers: Send extra headers
@@ -160,8 +160,8 @@ async def get_earnings(
timeout=timeout,
query=await async_maybe_transform(
{
- "start_date": start_date,
"end_date": end_date,
+ "start_date": start_date,
"type": type,
},
statement_get_earnings_params.StatementGetEarningsParams,
diff --git a/src/onlyfansapi/resources/statistics/statistics.py b/src/onlyfansapi/resources/statistics/statistics.py
index 36c1e040..dc947f8d 100644
--- a/src/onlyfansapi/resources/statistics/statistics.py
+++ b/src/onlyfansapi/resources/statistics/statistics.py
@@ -78,8 +78,8 @@ def calculate_total_transactions(
self,
account: str,
*,
- end_date: str,
- start_date: str,
+ end_date: str | Omit = omit,
+ start_date: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -184,6 +184,7 @@ def get_subscriber_metrics(
end_date: str,
start_date: str,
detailed: Optional[bool] | Omit = omit,
+ detailed_type: Optional[Literal["total", "renew", "new"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -204,6 +205,9 @@ def get_subscriber_metrics(
detailed: Include paid and free fan metrics. Will slow down the response time, and might
time out if timeframe is too large. Default = `false`
+ detailed_type: Use only with `detailed=true` - otherwise, it has no effect. Filter the
+ subscriber statistics (default = total)
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -226,6 +230,7 @@ def get_subscriber_metrics(
"end_date": end_date,
"start_date": start_date,
"detailed": detailed,
+ "detailed_type": detailed_type,
},
statistic_get_subscriber_metrics_params.StatisticGetSubscriberMetricsParams,
),
@@ -266,8 +271,8 @@ async def calculate_total_transactions(
self,
account: str,
*,
- end_date: str,
- start_date: str,
+ end_date: str | Omit = omit,
+ start_date: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -372,6 +377,7 @@ async def get_subscriber_metrics(
end_date: str,
start_date: str,
detailed: Optional[bool] | Omit = omit,
+ detailed_type: Optional[Literal["total", "renew", "new"]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -392,6 +398,9 @@ async def get_subscriber_metrics(
detailed: Include paid and free fan metrics. Will slow down the response time, and might
time out if timeframe is too large. Default = `false`
+ detailed_type: Use only with `detailed=true` - otherwise, it has no effect. Filter the
+ subscriber statistics (default = total)
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -414,6 +423,7 @@ async def get_subscriber_metrics(
"end_date": end_date,
"start_date": start_date,
"detailed": detailed,
+ "detailed_type": detailed_type,
},
statistic_get_subscriber_metrics_params.StatisticGetSubscriberMetricsParams,
),
diff --git a/src/onlyfansapi/resources/stories/stories.py b/src/onlyfansapi/resources/stories/stories.py
index e0f472e0..3cb0db75 100644
--- a/src/onlyfansapi/resources/stories/stories.py
+++ b/src/onlyfansapi/resources/stories/stories.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Optional
+from typing import Iterable, Optional
import httpx
@@ -70,6 +70,10 @@ def create(
account: str,
*,
media_files: SequenceNotStr[str],
+ canvas_height: int | Omit = omit,
+ canvas_width: int | Omit = omit,
+ question: story_create_params.Question | Omit = omit,
+ texts: Iterable[story_create_params.Text] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -78,11 +82,20 @@ def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> StoryCreateResponse:
"""
- Post a new media or vault file to your story.
+ Post a new media or vault file to your story, optionally with text overlays,
+ @mentions, and a question sticker. Overlay elements are rendered by OnlyFans on
+ top of your story media at view time.
Args:
- media_files: Array of media file upload prefixed_ids, or OF media IDs (required if price is
- not 0).
+ media_files: Array of media file upload prefixed_ids, or OF vault media IDs.
+
+ canvas_height: Canvas height overlay positions are relative to. Default `1920`.
+
+ canvas_width: Canvas width overlay positions are relative to. Default `1080`.
+
+ question: Interactive question sticker viewers can answer.
+
+ texts: Text and @mention overlays.
extra_headers: Send extra headers
@@ -96,7 +109,16 @@ def create(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
return self._post(
path_template("/api/{account}/stories", account=account),
- body=maybe_transform({"media_files": media_files}, story_create_params.StoryCreateParams),
+ body=maybe_transform(
+ {
+ "media_files": media_files,
+ "canvas_height": canvas_height,
+ "canvas_width": canvas_width,
+ "question": question,
+ "texts": texts,
+ },
+ story_create_params.StoryCreateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -405,6 +427,10 @@ async def create(
account: str,
*,
media_files: SequenceNotStr[str],
+ canvas_height: int | Omit = omit,
+ canvas_width: int | Omit = omit,
+ question: story_create_params.Question | Omit = omit,
+ texts: Iterable[story_create_params.Text] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -413,11 +439,20 @@ async def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> StoryCreateResponse:
"""
- Post a new media or vault file to your story.
+ Post a new media or vault file to your story, optionally with text overlays,
+ @mentions, and a question sticker. Overlay elements are rendered by OnlyFans on
+ top of your story media at view time.
Args:
- media_files: Array of media file upload prefixed_ids, or OF media IDs (required if price is
- not 0).
+ media_files: Array of media file upload prefixed_ids, or OF vault media IDs.
+
+ canvas_height: Canvas height overlay positions are relative to. Default `1920`.
+
+ canvas_width: Canvas width overlay positions are relative to. Default `1080`.
+
+ question: Interactive question sticker viewers can answer.
+
+ texts: Text and @mention overlays.
extra_headers: Send extra headers
@@ -431,7 +466,16 @@ async def create(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
return await self._post(
path_template("/api/{account}/stories", account=account),
- body=await async_maybe_transform({"media_files": media_files}, story_create_params.StoryCreateParams),
+ body=await async_maybe_transform(
+ {
+ "media_files": media_files,
+ "canvas_height": canvas_height,
+ "canvas_width": canvas_width,
+ "question": question,
+ "texts": texts,
+ },
+ story_create_params.StoryCreateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/onlyfansapi/resources/tracking_links/tracking_links.py b/src/onlyfansapi/resources/tracking_links/tracking_links.py
index 0d65bfbf..1dfe3aaa 100644
--- a/src/onlyfansapi/resources/tracking_links/tracking_links.py
+++ b/src/onlyfansapi/resources/tracking_links/tracking_links.py
@@ -161,13 +161,14 @@ def list(
account: str,
*,
end_date: Optional[str] | Omit = omit,
- limit: Optional[int] | Omit = omit,
- offset: Optional[int] | Omit = omit,
- sort: Optional[Literal["desc", "asc"]] | Omit = omit,
- sortby: Optional[Literal["claims", "created_date"]] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ sort: Literal["asc", "desc"] | Omit = omit,
+ sortby: Literal["claims", "created_date"] | Omit = omit,
start_date: Optional[str] | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
- with_deleted: Optional[bool] | Omit = omit,
+ synchronous: bool | Omit = omit,
+ with_deleted: Literal[0, 1] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -179,24 +180,24 @@ def list(
List all tracking links for the account and revenue data
Args:
- end_date: The end date for Tracking Links. Keep empty to get all.
+ end_date: The end date for tracking links. Keep empty to get all. Must not be greater than
+ 255 characters.
- limit: The number of tracking links to return. Default `3`
+ limit: The number of tracking links to return. Default `10`. Must be at least 1. Must
+ not be greater than 100.
- offset: The offset used for pagination. Default `0`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- sort: Sort the results. Default `desc`
+ sort: Sort direction. Default `desc`.
- sortby: Sort by subscriber count (claims), or creation date
+ sortby: Sort by subscriber count (`claims`) or creation date (`created_date`).
- start_date: The start date for Tracking Links. Keep empty to get all.
+ start_date: The start date for tracking links. Keep empty to get all. Must not be greater
+ than 255 characters.
- synchronous: Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+ synchronous: Wait for revenue calculation instead of processing it in the background.
- with_deleted: Whether or not to include deleted tracking links in the response. Default
- `false`
+ with_deleted: Whether to include deleted tracking links. Default `true`.
extra_headers: Send extra headers
@@ -220,6 +221,7 @@ def list(
"end_date": end_date,
"limit": limit,
"offset": offset,
+ "pagination": pagination,
"sort": sort,
"sortby": sortby,
"start_date": start_date,
@@ -626,13 +628,14 @@ async def list(
account: str,
*,
end_date: Optional[str] | Omit = omit,
- limit: Optional[int] | Omit = omit,
- offset: Optional[int] | Omit = omit,
- sort: Optional[Literal["desc", "asc"]] | Omit = omit,
- sortby: Optional[Literal["claims", "created_date"]] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
+ pagination: Literal[0, 1] | Omit = omit,
+ sort: Literal["asc", "desc"] | Omit = omit,
+ sortby: Literal["claims", "created_date"] | Omit = omit,
start_date: Optional[str] | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
- with_deleted: Optional[bool] | Omit = omit,
+ synchronous: bool | Omit = omit,
+ with_deleted: Literal[0, 1] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -644,24 +647,24 @@ async def list(
List all tracking links for the account and revenue data
Args:
- end_date: The end date for Tracking Links. Keep empty to get all.
+ end_date: The end date for tracking links. Keep empty to get all. Must not be greater than
+ 255 characters.
- limit: The number of tracking links to return. Default `3`
+ limit: The number of tracking links to return. Default `10`. Must be at least 1. Must
+ not be greater than 100.
- offset: The offset used for pagination. Default `0`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- sort: Sort the results. Default `desc`
+ sort: Sort direction. Default `desc`.
- sortby: Sort by subscriber count (claims), or creation date
+ sortby: Sort by subscriber count (`claims`) or creation date (`created_date`).
- start_date: The start date for Tracking Links. Keep empty to get all.
+ start_date: The start date for tracking links. Keep empty to get all. Must not be greater
+ than 255 characters.
- synchronous: Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+ synchronous: Wait for revenue calculation instead of processing it in the background.
- with_deleted: Whether or not to include deleted tracking links in the response. Default
- `false`
+ with_deleted: Whether to include deleted tracking links. Default `true`.
extra_headers: Send extra headers
@@ -685,6 +688,7 @@ async def list(
"end_date": end_date,
"limit": limit,
"offset": offset,
+ "pagination": pagination,
"sort": sort,
"sortby": sortby,
"start_date": start_date,
diff --git a/src/onlyfansapi/resources/transactions.py b/src/onlyfansapi/resources/transactions.py
index a9754027..b5f53391 100644
--- a/src/onlyfansapi/resources/transactions.py
+++ b/src/onlyfansapi/resources/transactions.py
@@ -69,7 +69,7 @@ def list(
marker: The marker used for pagination. Default: `null`
- start_date: The start date for transactions list. Default: `-30days`
+ start_date: The start date for the transactions list. Defaults to 30 days ago.
tips_source: Filter tips by source. Only applies when `type=tips`. Options: `profile`,
`post_all`, `chat`, `stream`, `story`
@@ -157,7 +157,7 @@ async def list(
marker: The marker used for pagination. Default: `null`
- start_date: The start date for transactions list. Default: `-30days`
+ start_date: The start date for the transactions list. Defaults to 30 days ago.
tips_source: Filter tips by source. Only applies when `type=tips`. Options: `profile`,
`post_all`, `chat`, `stream`, `story`
diff --git a/src/onlyfansapi/resources/trial_links/trial_links.py b/src/onlyfansapi/resources/trial_links/trial_links.py
index 5554ee41..89477194 100644
--- a/src/onlyfansapi/resources/trial_links/trial_links.py
+++ b/src/onlyfansapi/resources/trial_links/trial_links.py
@@ -173,12 +173,14 @@ def list(
self,
account: str,
*,
- limit: int,
- offset: int,
- field: Optional[Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]]
+ end_date: Optional[str] | Omit = omit,
+ field: Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]
| Omit = omit,
- sort: Optional[Literal["desc", "asc"]] | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
+ sort: Literal["asc", "desc"] | Omit = omit,
+ start_date: Optional[str] | Omit = omit,
+ synchronous: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -190,17 +192,22 @@ def list(
List all free trial links for the account, including the details and statistics
Args:
- limit: The number of trial links to return. Default `10`
+ end_date: The end date for trial links. Keep empty to get all. Must not be greater than
+ 255 characters.
- offset: The offset used for pagination. Default `0`
+ field: Field to sort by. Default `create_date`.
- field: Sort the results by a field. Default `create_date`
+ limit: The number of trial links to return. Default `10`. Must be at least 1. Must not
+ be greater than 100.
- sort: Sort the results. Default `desc`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- synchronous: Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+ sort: Sort direction. Default `desc`.
+
+ start_date: The start date for trial links. Keep empty to get all. Must not be greater than
+ 255 characters.
+
+ synchronous: Wait for revenue calculation instead of processing it in the background.
extra_headers: Send extra headers
@@ -221,10 +228,12 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "end_date": end_date,
+ "field": field,
"limit": limit,
"offset": offset,
- "field": field,
"sort": sort,
+ "start_date": start_date,
"synchronous": synchronous,
},
trial_link_list_params.TrialLinkListParams,
@@ -624,12 +633,14 @@ async def list(
self,
account: str,
*,
- limit: int,
- offset: int,
- field: Optional[Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]]
+ end_date: Optional[str] | Omit = omit,
+ field: Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]
| Omit = omit,
- sort: Optional[Literal["desc", "asc"]] | Omit = omit,
- synchronous: Optional[bool] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
+ sort: Literal["asc", "desc"] | Omit = omit,
+ start_date: Optional[str] | Omit = omit,
+ synchronous: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -641,17 +652,22 @@ async def list(
List all free trial links for the account, including the details and statistics
Args:
- limit: The number of trial links to return. Default `10`
+ end_date: The end date for trial links. Keep empty to get all. Must not be greater than
+ 255 characters.
- offset: The offset used for pagination. Default `0`
+ field: Field to sort by. Default `create_date`.
- field: Sort the results by a field. Default `create_date`
+ limit: The number of trial links to return. Default `10`. Must be at least 1. Must not
+ be greater than 100.
- sort: Sort the results. Default `desc`
+ offset: The offset used for pagination. Default `0`. Must be at least 0.
- synchronous: Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+ sort: Sort direction. Default `desc`.
+
+ start_date: The start date for trial links. Keep empty to get all. Must not be greater than
+ 255 characters.
+
+ synchronous: Wait for revenue calculation instead of processing it in the background.
extra_headers: Send extra headers
@@ -672,10 +688,12 @@ async def list(
timeout=timeout,
query=await async_maybe_transform(
{
+ "end_date": end_date,
+ "field": field,
"limit": limit,
"offset": offset,
- "field": field,
"sort": sort,
+ "start_date": start_date,
"synchronous": synchronous,
},
trial_link_list_params.TrialLinkListParams,
diff --git a/src/onlyfansapi/resources/user_lists/user_lists.py b/src/onlyfansapi/resources/user_lists/user_lists.py
index 44b1169b..8b89b85f 100644
--- a/src/onlyfansapi/resources/user_lists/user_lists.py
+++ b/src/onlyfansapi/resources/user_lists/user_lists.py
@@ -3,6 +3,7 @@
from __future__ import annotations
from typing import Optional
+from typing_extensions import Literal
import httpx
@@ -187,6 +188,7 @@ def list(
*,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
+ view: Literal["queue"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -194,8 +196,10 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> UserListListResponse:
- """
- Get a list of OnlyFans Collections - User Lists
+ """Get a list of OnlyFans Collections - User Lists.
+
+ If you only want to get User
+ Lists available for sending a Mass-Message, use `?view=queue`
Args:
limit: How many results to return in the request. Max. 50 user lists. Must be at
@@ -203,6 +207,9 @@ def list(
offset: Must be at least 0.
+ view: How to return the results. `queue` returns the user lists that are available for
+ Mass-Messaging.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -224,6 +231,7 @@ def list(
{
"limit": limit,
"offset": offset,
+ "view": view,
},
user_list_list_params.UserListListParams,
),
@@ -420,6 +428,7 @@ async def list(
*,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
+ view: Literal["queue"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -427,8 +436,10 @@ async def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> UserListListResponse:
- """
- Get a list of OnlyFans Collections - User Lists
+ """Get a list of OnlyFans Collections - User Lists.
+
+ If you only want to get User
+ Lists available for sending a Mass-Message, use `?view=queue`
Args:
limit: How many results to return in the request. Max. 50 user lists. Must be at
@@ -436,6 +447,9 @@ async def list(
offset: Must be at least 0.
+ view: How to return the results. `queue` returns the user lists that are available for
+ Mass-Messaging.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -457,6 +471,7 @@ async def list(
{
"limit": limit,
"offset": offset,
+ "view": view,
},
user_list_list_params.UserListListParams,
),
diff --git a/src/onlyfansapi/resources/user_lists/users.py b/src/onlyfansapi/resources/user_lists/users.py
index 19dbe816..7422373d 100644
--- a/src/onlyfansapi/resources/user_lists/users.py
+++ b/src/onlyfansapi/resources/user_lists/users.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+from typing import Any, cast
+
import httpx
from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
@@ -104,6 +106,7 @@ def add(
*,
account: str,
ids: SequenceNotStr[str],
+ skip_invalid: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -117,6 +120,14 @@ def add(
Args:
ids: Array of OnlyFans User IDs to be added into the list
+ skip_invalid: Set to `true` to skip the User IDs OnlyFans refuses instead of failing the whole
+ batch. We drop the rejected IDs and retry the remainder for you (up to 5
+ OnlyFans attempts, each costing 1 credit), then respond `200` with `data.added`
+ (the IDs that made it in) and `data.failed` (an object mapping each rejected
+ User ID to the reason OnlyFans gave). Note this changes the shape of `data` —
+ see the example responses. Failures that are not about individual users (e.g. an
+ invalid or inaccessible list ID) still return the regular `400`.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -129,13 +140,24 @@ def add(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not user_list_id:
raise ValueError(f"Expected a non-empty value for `user_list_id` but received {user_list_id!r}")
- return self._post(
- path_template("/api/{account}/user-lists/{user_list_id}/users", account=account, user_list_id=user_list_id),
- body=maybe_transform({"ids": ids}, user_add_params.UserAddParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ return cast(
+ UserAddResponse,
+ self._post(
+ path_template(
+ "/api/{account}/user-lists/{user_list_id}/users", account=account, user_list_id=user_list_id
+ ),
+ body=maybe_transform(
+ {
+ "ids": ids,
+ "skip_invalid": skip_invalid,
+ },
+ user_add_params.UserAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, UserAddResponse), # Union types cannot be passed in as arguments in the type system
),
- cast_to=UserAddResponse,
)
def clear(
@@ -391,6 +413,7 @@ async def add(
*,
account: str,
ids: SequenceNotStr[str],
+ skip_invalid: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -404,6 +427,14 @@ async def add(
Args:
ids: Array of OnlyFans User IDs to be added into the list
+ skip_invalid: Set to `true` to skip the User IDs OnlyFans refuses instead of failing the whole
+ batch. We drop the rejected IDs and retry the remainder for you (up to 5
+ OnlyFans attempts, each costing 1 credit), then respond `200` with `data.added`
+ (the IDs that made it in) and `data.failed` (an object mapping each rejected
+ User ID to the reason OnlyFans gave). Note this changes the shape of `data` —
+ see the example responses. Failures that are not about individual users (e.g. an
+ invalid or inaccessible list ID) still return the regular `400`.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -416,13 +447,24 @@ async def add(
raise ValueError(f"Expected a non-empty value for `account` but received {account!r}")
if not user_list_id:
raise ValueError(f"Expected a non-empty value for `user_list_id` but received {user_list_id!r}")
- return await self._post(
- path_template("/api/{account}/user-lists/{user_list_id}/users", account=account, user_list_id=user_list_id),
- body=await async_maybe_transform({"ids": ids}, user_add_params.UserAddParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ return cast(
+ UserAddResponse,
+ await self._post(
+ path_template(
+ "/api/{account}/user-lists/{user_list_id}/users", account=account, user_list_id=user_list_id
+ ),
+ body=await async_maybe_transform(
+ {
+ "ids": ids,
+ "skip_invalid": skip_invalid,
+ },
+ user_add_params.UserAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, UserAddResponse), # Union types cannot be passed in as arguments in the type system
),
- cast_to=UserAddResponse,
)
async def clear(
diff --git a/src/onlyfansapi/resources/webhooks.py b/src/onlyfansapi/resources/webhooks.py
index fff7e940..c704b488 100644
--- a/src/onlyfansapi/resources/webhooks.py
+++ b/src/onlyfansapi/resources/webhooks.py
@@ -67,16 +67,19 @@ def create(
Create a new webhook for your Team
Args:
- account_scope: The account scope for the webhook. Use "global" for all accounts, "inclusive"
- for only selected accounts, or "exclusive" for all except selected accounts.
+ account_scope: The account scope for the webhook (OnlyFans and Fansly webhooks alike). Use
+ "global" for all accounts, "inclusive" for only selected accounts, or
+ "exclusive" for all except selected accounts.
endpoint_url: The URL of your webhook endpoint.
events: An array of webhook events to subscribe to. For all options, refer to our **List
- Available Events** endpoint.
+ Available Events** endpoint. A webhook is single-platform: subscribe to either
+ OnlyFans events or Fansly (`fansly.*`) events, never both in one webhook.
- account_ids: An array of account IDs to apply the scope to. Required unless account_scope is
- "global".
+ account_ids: An array of account IDs to apply the scope to. Use OnlyFans account IDs
+ (`acct_...`) for OnlyFans webhooks and Fansly account IDs (`fansly_acct_...`)
+ for Fansly webhooks. Required unless account_scope is "global".
signing_secret: Optionally, add a signing secret to protect your webhook.
@@ -159,16 +162,19 @@ def update(
Update an existing webhook
Args:
- account_scope: The account scope for the webhook. Use "global" for all accounts, "inclusive"
- for only selected accounts, or "exclusive" for all except selected accounts.
+ account_scope: The account scope for the webhook (OnlyFans and Fansly webhooks alike). Use
+ "global" for all accounts, "inclusive" for only selected accounts, or
+ "exclusive" for all except selected accounts.
endpoint_url: The URL of your webhook endpoint.
events: An array of webhook events to subscribe to. For all options, refer to our **List
- Available Events** endpoint.
+ Available Events** endpoint. A webhook is single-platform: subscribe to either
+ OnlyFans events or Fansly (`fansly.*`) events, never both in one webhook.
- account_ids: An array of account IDs to apply the scope to. Required unless account_scope is
- "global".
+ account_ids: An array of account IDs to apply the scope to. Use OnlyFans account IDs
+ (`acct_...`) for OnlyFans webhooks and Fansly account IDs (`fansly_acct_...`)
+ for Fansly webhooks. Required unless account_scope is "global".
enabled: Optionally, enabled/disable the webhook. This will stop/resume the sending of
events, without having to delete the webhook.
@@ -312,16 +318,19 @@ async def create(
Create a new webhook for your Team
Args:
- account_scope: The account scope for the webhook. Use "global" for all accounts, "inclusive"
- for only selected accounts, or "exclusive" for all except selected accounts.
+ account_scope: The account scope for the webhook (OnlyFans and Fansly webhooks alike). Use
+ "global" for all accounts, "inclusive" for only selected accounts, or
+ "exclusive" for all except selected accounts.
endpoint_url: The URL of your webhook endpoint.
events: An array of webhook events to subscribe to. For all options, refer to our **List
- Available Events** endpoint.
+ Available Events** endpoint. A webhook is single-platform: subscribe to either
+ OnlyFans events or Fansly (`fansly.*`) events, never both in one webhook.
- account_ids: An array of account IDs to apply the scope to. Required unless account_scope is
- "global".
+ account_ids: An array of account IDs to apply the scope to. Use OnlyFans account IDs
+ (`acct_...`) for OnlyFans webhooks and Fansly account IDs (`fansly_acct_...`)
+ for Fansly webhooks. Required unless account_scope is "global".
signing_secret: Optionally, add a signing secret to protect your webhook.
@@ -404,16 +413,19 @@ async def update(
Update an existing webhook
Args:
- account_scope: The account scope for the webhook. Use "global" for all accounts, "inclusive"
- for only selected accounts, or "exclusive" for all except selected accounts.
+ account_scope: The account scope for the webhook (OnlyFans and Fansly webhooks alike). Use
+ "global" for all accounts, "inclusive" for only selected accounts, or
+ "exclusive" for all except selected accounts.
endpoint_url: The URL of your webhook endpoint.
events: An array of webhook events to subscribe to. For all options, refer to our **List
- Available Events** endpoint.
+ Available Events** endpoint. A webhook is single-platform: subscribe to either
+ OnlyFans events or Fansly (`fansly.*`) events, never both in one webhook.
- account_ids: An array of account IDs to apply the scope to. Required unless account_scope is
- "global".
+ account_ids: An array of account IDs to apply the scope to. Use OnlyFans account IDs
+ (`acct_...`) for OnlyFans webhooks and Fansly account IDs (`fansly_acct_...`)
+ for Fansly webhooks. Required unless account_scope is "global".
enabled: Optionally, enabled/disable the webhook. This will stop/resume the sending of
events, without having to delete the webhook.
diff --git a/src/onlyfansapi/types/__init__.py b/src/onlyfansapi/types/__init__.py
index 6d3ddf1a..8370c488 100644
--- a/src/onlyfansapi/types/__init__.py
+++ b/src/onlyfansapi/types/__init__.py
@@ -66,7 +66,6 @@
from .user_retrieve_response import UserRetrieveResponse as UserRetrieveResponse
from .data_export_list_params import DataExportListParams as DataExportListParams
from .fan_list_expired_params import FanListExpiredParams as FanListExpiredParams
-from .media_download_response import MediaDownloadResponse as MediaDownloadResponse
from .post_unarchive_response import PostUnarchiveResponse as PostUnarchiveResponse
from .profile_retrieve_params import ProfileRetrieveParams as ProfileRetrieveParams
from .promotion_create_params import PromotionCreateParams as PromotionCreateParams
@@ -115,7 +114,6 @@
from .fan_set_custom_name_params import FanSetCustomNameParams as FanSetCustomNameParams
from .giphy_list_trending_params import GiphyListTrendingParams as GiphyListTrendingParams
from .mass_messaging_send_params import MassMessagingSendParams as MassMessagingSendParams
-from .message_attach_tags_params import MessageAttachTagsParams as MessageAttachTagsParams
from .notification_list_response import NotificationListResponse as NotificationListResponse
from .smart_link_create_response import SmartLinkCreateResponse as SmartLinkCreateResponse
from .smart_link_delete_response import SmartLinkDeleteResponse as SmartLinkDeleteResponse
@@ -143,7 +141,6 @@
from .mass_messaging_list_response import MassMessagingListResponse as MassMessagingListResponse
from .mass_messaging_send_response import MassMessagingSendResponse as MassMessagingSendResponse
from .mass_messaging_update_params import MassMessagingUpdateParams as MassMessagingUpdateParams
-from .message_attach_tags_response import MessageAttachTagsResponse as MessageAttachTagsResponse
from .smart_link_retrieve_response import SmartLinkRetrieveResponse as SmartLinkRetrieveResponse
from .trial_link_retrieve_response import TrialLinkRetrieveResponse as TrialLinkRetrieveResponse
from .webhook_list_events_response import WebhookListEventsResponse as WebhookListEventsResponse
diff --git a/src/onlyfansapi/types/analytics/financial/profitability_get_history_response.py b/src/onlyfansapi/types/analytics/financial/profitability_get_history_response.py
index bca137b8..7fa2af0d 100644
--- a/src/onlyfansapi/types/analytics/financial/profitability_get_history_response.py
+++ b/src/onlyfansapi/types/analytics/financial/profitability_get_history_response.py
@@ -1,25 +1,49 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import List, Optional
-from typing_extensions import TypeAlias
+
+from pydantic import Field as FieldInfo
from ...._models import BaseModel
-__all__ = ["ProfitabilityGetHistoryResponse", "ProfitabilityGetHistoryResponseItem"]
+__all__ = ["ProfitabilityGetHistoryResponse", "Data"]
+
+
+class Data(BaseModel):
+ active_milestones: Optional[str] = FieldInfo(alias="activeMilestones", default=None)
+
+ agency_earnings: Optional[str] = FieldInfo(alias="agencyEarnings", default=None)
+
+ commission_amount: Optional[str] = FieldInfo(alias="commissionAmount", default=None)
+
+ commission_rate: Optional[str] = FieldInfo(alias="commissionRate", default=None)
+ costs: Optional[List[object]] = None
-class ProfitabilityGetHistoryResponseItem(BaseModel):
- gross_revenue: Optional[float] = None
+ creator_name: Optional[str] = FieldInfo(alias="creatorName", default=None)
- margin: Optional[float] = None
+ has_commission_for_period: Optional[bool] = FieldInfo(alias="hasCommissionForPeriod", default=None)
+
+ has_costs_for_period: Optional[bool] = FieldInfo(alias="hasCostsForPeriod", default=None)
+
+ margin_percentage: Optional[str] = FieldInfo(alias="marginPercentage", default=None)
month: Optional[int] = None
- net_revenue: Optional[float] = None
+ only_fans_user_id: Optional[int] = FieldInfo(alias="onlyFansUserId", default=None)
+
+ profit: Optional[str] = None
+
+ projected_net: Optional[str] = FieldInfo(alias="projectedNet", default=None)
+
+ rate_periods: Optional[List[object]] = FieldInfo(alias="ratePeriods", default=None)
+
+ referral_note: Optional[str] = FieldInfo(alias="referralNote", default=None)
- profit: Optional[float] = None
+ total_costs: Optional[str] = FieldInfo(alias="totalCosts", default=None)
year: Optional[int] = None
-ProfitabilityGetHistoryResponse: TypeAlias = List[ProfitabilityGetHistoryResponseItem]
+class ProfitabilityGetHistoryResponse(BaseModel):
+ data: Optional[List[Data]] = None
diff --git a/src/onlyfansapi/types/analytics/financial/profitability_get_profitability_response.py b/src/onlyfansapi/types/analytics/financial/profitability_get_profitability_response.py
index 9670755f..8cacbcc4 100644
--- a/src/onlyfansapi/types/analytics/financial/profitability_get_profitability_response.py
+++ b/src/onlyfansapi/types/analytics/financial/profitability_get_profitability_response.py
@@ -1,29 +1,49 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import List, Optional
-from typing_extensions import TypeAlias
+
+from pydantic import Field as FieldInfo
from ...._models import BaseModel
-__all__ = ["ProfitabilityGetProfitabilityResponse", "ProfitabilityGetProfitabilityResponseItem"]
+__all__ = ["ProfitabilityGetProfitabilityResponse", "Data"]
+
+
+class Data(BaseModel):
+ active_milestones: Optional[str] = FieldInfo(alias="activeMilestones", default=None)
+
+ agency_earnings: Optional[str] = FieldInfo(alias="agencyEarnings", default=None)
+
+ commission_amount: Optional[str] = FieldInfo(alias="commissionAmount", default=None)
+
+ commission_rate: Optional[str] = FieldInfo(alias="commissionRate", default=None)
+
+ costs: Optional[List[object]] = None
+
+ creator_name: Optional[str] = FieldInfo(alias="creatorName", default=None)
+
+ has_commission_for_period: Optional[bool] = FieldInfo(alias="hasCommissionForPeriod", default=None)
+
+ has_costs_for_period: Optional[bool] = FieldInfo(alias="hasCostsForPeriod", default=None)
+ margin_percentage: Optional[str] = FieldInfo(alias="marginPercentage", default=None)
-class ProfitabilityGetProfitabilityResponseItem(BaseModel):
- commission: Optional[float] = None
+ month: Optional[int] = None
- creator_id: Optional[int] = None
+ only_fans_user_id: Optional[int] = FieldInfo(alias="onlyFansUserId", default=None)
- gross_revenue: Optional[float] = None
+ profit: Optional[str] = None
- margin: Optional[float] = None
+ projected_net: Optional[str] = FieldInfo(alias="projectedNet", default=None)
- name: Optional[str] = None
+ rate_periods: Optional[List[object]] = FieldInfo(alias="ratePeriods", default=None)
- net_revenue: Optional[float] = None
+ referral_note: Optional[str] = FieldInfo(alias="referralNote", default=None)
- profit: Optional[float] = None
+ total_costs: Optional[str] = FieldInfo(alias="totalCosts", default=None)
- total_costs: Optional[float] = None
+ year: Optional[int] = None
-ProfitabilityGetProfitabilityResponse: TypeAlias = List[ProfitabilityGetProfitabilityResponseItem]
+class ProfitabilityGetProfitabilityResponse(BaseModel):
+ data: Optional[List[Data]] = None
diff --git a/src/onlyfansapi/types/authenticate_start_params.py b/src/onlyfansapi/types/authenticate_start_params.py
index 0c7d0590..9a514021 100644
--- a/src/onlyfansapi/types/authenticate_start_params.py
+++ b/src/onlyfansapi/types/authenticate_start_params.py
@@ -53,7 +53,7 @@ class AuthenticateStartParams(TypedDict, total=False):
Required when auth_type is `email_password`.
"""
- proxy_country: Annotated[Literal["us", "uk"], PropertyInfo(alias="proxyCountry")]
+ proxy_country: Annotated[Literal["us", "uk", "gb"], PropertyInfo(alias="proxyCountry")]
"""The country of the managed proxy server you want to use.
Eg. "us" for United States. Cannot be used together with customProxy.
diff --git a/src/onlyfansapi/types/chat_list_media_params.py b/src/onlyfansapi/types/chat_list_media_params.py
index 8be91bf7..43a4cc6a 100644
--- a/src/onlyfansapi/types/chat_list_media_params.py
+++ b/src/onlyfansapi/types/chat_list_media_params.py
@@ -18,7 +18,10 @@ class ChatListMediaParams(TypedDict, total=False):
"""Number of medias to skip for pagination"""
skip_users: str
- """Whether to skip user details in response (all or none). Default = all"""
+ """Whether to skip user details in the response (`all` or `none`).
+
+ Defaults to `all`.
+ """
type: Optional[Literal["photos", "videos", "audios"]]
"""Filter by specific media types. Keep empty to return all."""
diff --git a/src/onlyfansapi/types/chat_list_params.py b/src/onlyfansapi/types/chat_list_params.py
index 8f059008..0bfd48d9 100644
--- a/src/onlyfansapi/types/chat_list_params.py
+++ b/src/onlyfansapi/types/chat_list_params.py
@@ -24,4 +24,7 @@ class ChatListParams(TypedDict, total=False):
"""Search query to filter chats"""
skip_users: Literal["all", "none"]
- """Whether to skip user details in response (all or none). Default = all"""
+ """Whether to skip user details in the response (`all` or `none`).
+
+ Defaults to `all`.
+ """
diff --git a/src/onlyfansapi/types/chats/message_list_params.py b/src/onlyfansapi/types/chats/message_list_params.py
index d7c0bd75..ded63216 100644
--- a/src/onlyfansapi/types/chats/message_list_params.py
+++ b/src/onlyfansapi/types/chats/message_list_params.py
@@ -36,4 +36,4 @@ class MessageListParams(TypedDict, total=False):
"""Sort order for messages (desc or asc)"""
skip_users: str
- """Whether to skip user details (all or none)"""
+ """Whether to skip user details (`all` or `none`)."""
diff --git a/src/onlyfansapi/types/chats/message_send_params.py b/src/onlyfansapi/types/chats/message_send_params.py
index 12842b4d..16cc13aa 100644
--- a/src/onlyfansapi/types/chats/message_send_params.py
+++ b/src/onlyfansapi/types/chats/message_send_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Iterable
-from typing_extensions import Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
from ..._utils import PropertyInfo
@@ -13,6 +13,16 @@
class MessageSendParams(TypedDict, total=False):
account: Required[str]
+ block_banned_words: Annotated[
+ Literal["strict_ban", "risky", "replace_soften"], PropertyInfo(alias="blockBannedWords")
+ ]
+ """
+ Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+ """
+
giphy_id: Annotated[str, PropertyInfo(alias="giphyId")]
"""The ID of the Giphy GIF to attach to the message.
@@ -35,8 +45,8 @@ class MessageSendParams(TypedDict, total=False):
provided.
"""
- price: int
- """Price for paid content (0 or between 3-200).
+ price: float
+ """Price for paid content in USD (0 or between 3-200).
In case this is not zero, **mediaFiles** is required
"""
@@ -58,3 +68,5 @@ class MessageSendParams(TypedDict, total=False):
text: str
"""The message text content. Required unless a media file is present."""
+
+ idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")]
diff --git a/src/onlyfansapi/types/client_session_create_params.py b/src/onlyfansapi/types/client_session_create_params.py
index 27bb09b9..89116429 100644
--- a/src/onlyfansapi/types/client_session_create_params.py
+++ b/src/onlyfansapi/types/client_session_create_params.py
@@ -15,4 +15,4 @@ class ClientSessionCreateParams(TypedDict, total=False):
client_reference_id: str
"""Your Internal Reference ID for the connected account."""
- proxy_country: Optional[Literal["us", "uk"]]
+ proxy_country: Optional[Literal["us", "uk", "gb"]]
diff --git a/src/onlyfansapi/types/data_export_create_params.py b/src/onlyfansapi/types/data_export_create_params.py
index 6e33559f..0bba8553 100644
--- a/src/onlyfansapi/types/data_export_create_params.py
+++ b/src/onlyfansapi/types/data_export_create_params.py
@@ -18,8 +18,9 @@ class DataExportCreateParams(TypedDict, total=False):
"""The output file format.
Supported formats vary by export type: `csv` or `xlsx` for transactions,
- chat_messages, trial_links, tracking_links, smart_links, payouts, chargebacks,
- public_profiles, fans, followings; `zip` for media_vault.
+ chat_messages, fansly_chat_messages, trial_links, tracking_links, smart_links,
+ payouts, chargebacks, public_profiles, fans, followings, profile_visitors; `zip`
+ for media_vault.
"""
start_date: Required[str]
@@ -38,14 +39,23 @@ class DataExportCreateParams(TypedDict, total=False):
"public_profiles",
"fans",
"followings",
+ "profile_visitors",
+ "fansly_chat_messages",
]
]
- """The type of data to export"""
+ """The type of data to export.
+
+ Use `fansly_chat_messages` to export Fansly chat messages (all other types are
+ OnlyFans). `profile_visitors` returns one row per account per day, scraped one
+ day at a time so the daily numbers are not aggregated away by OnlyFans.
+ """
account_ids: SequenceNotStr[str]
"""Array of account prefixed IDs to export data from.
- Not required for `public_profiles` type.
+ Not required for `public_profiles` type. For `fansly_chat_messages`, pass Fansly
+ account prefixed IDs (`fansly_acct_...`); all other types take OnlyFans account
+ IDs.
"""
auto_start: bool
@@ -63,15 +73,19 @@ class DataExportCreateParams(TypedDict, total=False):
For `chat_messages`: `maxMessages` (required per account, max 10,000,000),
`maxChats` (optional per-account chat scrape limit), `skipMassMessages`
(optional, bool), `chatIds` (optional array of numeric fan/chat IDs; filters
- output and can drastically reduce totals). For `media_vault`: `mediaType`
- (required, one of: `all`, `photo`, `gif`, `video`, `audio`). For `fans`: `type`
- (required, one of: `all`, `active`, `expired`, `latest`). For `followings`:
- `type` (required, one of: `all`, `active`, `expired`). For `public_profiles`:
- `query` (optional, full-text search), `gender` (optional, filter: male, female,
- trans, couple), `minSubscribePrice` (optional, USD), `maxSubscribePrice`
- (optional, USD), `location` (optional), `minPostsCount` (optional, minimum
- posts), `minPhotosCount` (optional, minimum photos), `minVideosCount` (optional,
- minimum videos), `minSubscribersCount` (optional, minimum subscribers),
+ output and can drastically reduce totals). For `fansly_chat_messages`:
+ `maxMessages` (required per account, max 10,000,000), `maxChats` (optional
+ per-account chat scrape limit), `chatIds` (optional array of Fansly group ID
+ strings; filters output and can drastically reduce totals). For `media_vault`:
+ `mediaType` (required, one of: `all`, `photo`, `gif`, `video`, `audio`). For
+ `fans`: `type` (required, one of: `all`, `active`, `expired`, `latest`). For
+ `followings`: `type` (required, one of: `all`, `active`, `expired`). For
+ `public_profiles`: `query` (optional, full-text search), `gender` (optional,
+ filter: male, female, trans, couple), `minSubscribePrice` (optional, USD),
+ `maxSubscribePrice` (optional, USD), `location` (optional), `minPostsCount`
+ (optional, minimum posts), `minPhotosCount` (optional, minimum photos),
+ `minVideosCount` (optional, minimum videos), `minSubscribersCount` (optional,
+ minimum subscribers), `maxSubscribersCount` (optional, maximum subscribers),
`minJoinDate` (optional, ISO 8601 date), `minLastSeenAt` (optional, ISO 8601
date), `createdAtFrom` (optional, ISO 8601 date, profile added to DB after),
`createdAtTo` (optional, ISO 8601 date, profile added to DB before), `instagram`
diff --git a/src/onlyfansapi/types/data_export_list_params.py b/src/onlyfansapi/types/data_export_list_params.py
index 94abb046..28030250 100644
--- a/src/onlyfansapi/types/data_export_list_params.py
+++ b/src/onlyfansapi/types/data_export_list_params.py
@@ -34,8 +34,13 @@ class DataExportListParams(TypedDict, total=False):
"media_vault",
"trial_links",
"tracking_links",
+ "smart_links",
"payouts",
"chargebacks",
"public_profiles",
+ "fans",
+ "followings",
+ "profile_visitors",
+ "fansly_chat_messages",
]
"""Filter by export type"""
diff --git a/src/onlyfansapi/types/data_export_list_response.py b/src/onlyfansapi/types/data_export_list_response.py
index 76ca5269..a721c5ba 100644
--- a/src/onlyfansapi/types/data_export_list_response.py
+++ b/src/onlyfansapi/types/data_export_list_response.py
@@ -80,6 +80,8 @@ class DataData(BaseModel):
failed_at: Optional[str] = None
+ failed_downloads: Optional[int] = None
+
failed_reason: Optional[str] = None
file_type: Optional[str] = None
diff --git a/src/onlyfansapi/types/data_export_retrieve_response.py b/src/onlyfansapi/types/data_export_retrieve_response.py
index bcfde627..d9cc2ebb 100644
--- a/src/onlyfansapi/types/data_export_retrieve_response.py
+++ b/src/onlyfansapi/types/data_export_retrieve_response.py
@@ -74,6 +74,8 @@ class Data(BaseModel):
failed_at: Optional[str] = None
+ failed_downloads: Optional[int] = None
+
failed_reason: Optional[str] = None
file_type: Optional[str] = None
diff --git a/src/onlyfansapi/types/engagement/message_get_message_buyers_params.py b/src/onlyfansapi/types/engagement/message_get_message_buyers_params.py
index 5d382563..8df10841 100644
--- a/src/onlyfansapi/types/engagement/message_get_message_buyers_params.py
+++ b/src/onlyfansapi/types/engagement/message_get_message_buyers_params.py
@@ -20,7 +20,7 @@ class MessageGetMessageBuyersParams(TypedDict, total=False):
"""Offset for pagination (default = 0)"""
skip_users: str
- """Optional flag for subsequent pages (example: all)"""
+ """Optional flag for subsequent pages (example: all)."""
skip_users_dups: int
"""Skip duplicate users in results (0/1). Default = 1"""
diff --git a/src/onlyfansapi/types/engagement/message_get_top_message_params.py b/src/onlyfansapi/types/engagement/message_get_top_message_params.py
index 7708fd7b..5fe72470 100644
--- a/src/onlyfansapi/types/engagement/message_get_top_message_params.py
+++ b/src/onlyfansapi/types/engagement/message_get_top_message_params.py
@@ -13,7 +13,7 @@ class MessageGetTopMessageParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
"""The end date for the period.
- Keep empty to retrieve until now. MUST BE DATE AFTER `startDate`.
+ Keep empty to retrieve until now. It must be after `startDate`.
"""
start_date: Annotated[str, PropertyInfo(alias="startDate")]
diff --git a/src/onlyfansapi/types/engagement/messages/direct_message_chart_params.py b/src/onlyfansapi/types/engagement/messages/direct_message_chart_params.py
index 989a95be..6ed59a3f 100644
--- a/src/onlyfansapi/types/engagement/messages/direct_message_chart_params.py
+++ b/src/onlyfansapi/types/engagement/messages/direct_message_chart_params.py
@@ -11,7 +11,7 @@
class DirectMessageChartParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
- """End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`."""
+ """End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`."""
start_date: Annotated[str, PropertyInfo(alias="startDate")]
"""Start of the chart window in `Y-m-d H:i:s` format."""
diff --git a/src/onlyfansapi/types/engagement/messages/direct_message_list_params.py b/src/onlyfansapi/types/engagement/messages/direct_message_list_params.py
index c167da0e..9793f45f 100644
--- a/src/onlyfansapi/types/engagement/messages/direct_message_list_params.py
+++ b/src/onlyfansapi/types/engagement/messages/direct_message_list_params.py
@@ -13,7 +13,7 @@ class DirectMessageListParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
"""The latest message to retrieve.
- Keep empty to get all. MUST BE DATE AFTER `startDate`. This is also used for
+ Keep empty to get all. It must be after `startDate` and is also used for
pagination.
"""
diff --git a/src/onlyfansapi/types/engagement/messages/mass_message_chart_params.py b/src/onlyfansapi/types/engagement/messages/mass_message_chart_params.py
index d4d427e3..5d0c340b 100644
--- a/src/onlyfansapi/types/engagement/messages/mass_message_chart_params.py
+++ b/src/onlyfansapi/types/engagement/messages/mass_message_chart_params.py
@@ -11,7 +11,7 @@
class MassMessageChartParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
- """End of the chart window in `Y-m-d H:i:s` format. Must be after `startDate`."""
+ """End of the chart window in `Y-m-d H:i:s` format. It must be after `startDate`."""
start_date: Annotated[str, PropertyInfo(alias="startDate")]
"""Start of the chart window in `Y-m-d H:i:s` format."""
diff --git a/src/onlyfansapi/types/engagement/messages/mass_message_list_params.py b/src/onlyfansapi/types/engagement/messages/mass_message_list_params.py
index 2256ffa7..4085ebbb 100644
--- a/src/onlyfansapi/types/engagement/messages/mass_message_list_params.py
+++ b/src/onlyfansapi/types/engagement/messages/mass_message_list_params.py
@@ -13,7 +13,7 @@ class MassMessageListParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
"""The latest message to retrieve.
- Keep empty to get all. MUST BE DATE AFTER `startDate`. This is also used for
+ Keep empty to get all. It must be after `startDate` and is also used for
pagination.
"""
diff --git a/src/onlyfansapi/types/fan_list_active_params.py b/src/onlyfansapi/types/fan_list_active_params.py
index a87a84e0..d85309cd 100644
--- a/src/onlyfansapi/types/fan_list_active_params.py
+++ b/src/onlyfansapi/types/fan_list_active_params.py
@@ -12,9 +12,10 @@ class FanListActiveParams(TypedDict, total=False):
filter: Filter
limit: int
- """Number of fans to return (1-50).
+ """Number of fans to return (1-20).
- Must be at least 1. Must not be greater than 20.
+ OnlyFans does not allow more than 20 per page. Must be at least 1. Must not be
+ greater than 20.
"""
offset: int
@@ -29,13 +30,57 @@ class FanListActiveParams(TypedDict, total=False):
class Filter(TypedDict, total=False):
duration: int
- """Filter by minimum subscription duration in months. Must be at least 0."""
+ """Filter by minimum subscription duration in months.
+
+ Must use bracket syntax: filter[duration]=1 — the dot form (filter.duration=1)
+ is rejected with a 422, because PHP rewrites it to `filter_duration` and the
+ filter could not be applied. Must be at least 0.
+ """
+
+ max_total_spent: float
+ """
+ Filter by **maximum** amount total spent by a fan — use
+ `filter[max_total_spent]=0` to isolate fans who have never spent. Combine with
+ `filter[total_spent]` for a range. Must use bracket syntax:
+ filter[max_total_spent]=0 — the dot form is rejected with a 422, because PHP
+ rewrites it to `filter_max_total_spent` and the filter could not be applied.
+
+ OnlyFans itself has no maximum-spend filter, so this one is resolved against
+ OnlyFansAPI's own fan index instead of being proxied. The fan objects in
+ `data.list` are still fetched live from OnlyFans and are re-checked against your
+ filters before being returned, but only fans we have already indexed for this
+ account can appear. Each response reports its own coverage under `data._source`;
+ when `data._source.is_complete` is `false` a full-base backfill is queued
+ automatically, so retry later for a complete answer.
+
+ `data._source.omitted_from_page` counts fans that matched your filters but which
+ OnlyFans returned no usable data for on that page (a deleted account, or a
+ partial response). They are left out of `data.list` and not revisited later in
+ the same walk, so a non-zero value means that page was short — start a fresh
+ walk to retry them. Cannot be combined with `filter[online]`. Must be at
+ least 0.
+ """
online: Optional[Literal[1, 0]]
- """Filter by online status (`1` for online fans)."""
+ """Filter by online status (`1` for online fans).
+
+ Must use bracket syntax: filter[online]=1 — the dot form (filter.online=1) is
+ rejected with a 422, because PHP rewrites it to `filter_online` and the filter
+ could not be applied.
+ """
tips: int
- """Filter by minimum tips. Must be at least 0."""
+ """Filter by minimum tips.
+
+ Must use bracket syntax: filter[tips]=100 — the dot form (filter.tips=100) is
+ rejected with a 422, because PHP rewrites it to `filter_tips` and the filter
+ could not be applied. Must be at least 0.
+ """
total_spent: int
- """Filter by minimum amount total spent by a fan. Must be at least 0."""
+ """Filter by minimum amount total spent by a fan.
+
+ Must use bracket syntax: filter[total_spent]=100 — the dot form
+ (filter.total_spent=100) is rejected with a 422, because PHP rewrites it to
+ `filter_total_spent` and the filter could not be applied. Must be at least 0.
+ """
diff --git a/src/onlyfansapi/types/fan_list_all_params.py b/src/onlyfansapi/types/fan_list_all_params.py
index 87a19c10..fd24932a 100644
--- a/src/onlyfansapi/types/fan_list_all_params.py
+++ b/src/onlyfansapi/types/fan_list_all_params.py
@@ -12,9 +12,10 @@ class FanListAllParams(TypedDict, total=False):
filter: Filter
limit: int
- """Number of fans to return (1-50).
+ """Number of fans to return (1-20).
- Must be at least 1. Must not be greater than 20.
+ OnlyFans does not allow more than 20 per page. Must be at least 1. Must not be
+ greater than 20.
"""
offset: int
@@ -29,13 +30,57 @@ class FanListAllParams(TypedDict, total=False):
class Filter(TypedDict, total=False):
duration: int
- """Filter by minimum subscription duration in months. Must be at least 0."""
+ """Filter by minimum subscription duration in months.
+
+ Must use bracket syntax: filter[duration]=1 — the dot form (filter.duration=1)
+ is rejected with a 422, because PHP rewrites it to `filter_duration` and the
+ filter could not be applied. Must be at least 0.
+ """
+
+ max_total_spent: float
+ """
+ Filter by **maximum** amount total spent by a fan — use
+ `filter[max_total_spent]=0` to isolate fans who have never spent. Combine with
+ `filter[total_spent]` for a range. Must use bracket syntax:
+ filter[max_total_spent]=0 — the dot form is rejected with a 422, because PHP
+ rewrites it to `filter_max_total_spent` and the filter could not be applied.
+
+ OnlyFans itself has no maximum-spend filter, so this one is resolved against
+ OnlyFansAPI's own fan index instead of being proxied. The fan objects in
+ `data.list` are still fetched live from OnlyFans and are re-checked against your
+ filters before being returned, but only fans we have already indexed for this
+ account can appear. Each response reports its own coverage under `data._source`;
+ when `data._source.is_complete` is `false` a full-base backfill is queued
+ automatically, so retry later for a complete answer.
+
+ `data._source.omitted_from_page` counts fans that matched your filters but which
+ OnlyFans returned no usable data for on that page (a deleted account, or a
+ partial response). They are left out of `data.list` and not revisited later in
+ the same walk, so a non-zero value means that page was short — start a fresh
+ walk to retry them. Cannot be combined with `filter[online]`. Must be at
+ least 0.
+ """
online: Optional[Literal[1, 0]]
- """Filter by online status (`1` for online fans)."""
+ """Filter by online status (`1` for online fans).
+
+ Must use bracket syntax: filter[online]=1 — the dot form (filter.online=1) is
+ rejected with a 422, because PHP rewrites it to `filter_online` and the filter
+ could not be applied.
+ """
tips: int
- """Filter by minimum tips. Must be at least 0."""
+ """Filter by minimum tips.
+
+ Must use bracket syntax: filter[tips]=100 — the dot form (filter.tips=100) is
+ rejected with a 422, because PHP rewrites it to `filter_tips` and the filter
+ could not be applied. Must be at least 0.
+ """
total_spent: int
- """Filter by minimum amount total spent by a fan. Must be at least 0."""
+ """Filter by minimum amount total spent by a fan.
+
+ Must use bracket syntax: filter[total_spent]=100 — the dot form
+ (filter.total_spent=100) is rejected with a 422, because PHP rewrites it to
+ `filter_total_spent` and the filter could not be applied. Must be at least 0.
+ """
diff --git a/src/onlyfansapi/types/fan_list_expired_params.py b/src/onlyfansapi/types/fan_list_expired_params.py
index 1643328e..5f07a378 100644
--- a/src/onlyfansapi/types/fan_list_expired_params.py
+++ b/src/onlyfansapi/types/fan_list_expired_params.py
@@ -12,9 +12,10 @@ class FanListExpiredParams(TypedDict, total=False):
filter: Filter
limit: int
- """Number of fans to return (1-50).
+ """Number of fans to return (1-20).
- Must be at least 1. Must not be greater than 20.
+ OnlyFans does not allow more than 20 per page. Must be at least 1. Must not be
+ greater than 20.
"""
offset: int
@@ -29,13 +30,57 @@ class FanListExpiredParams(TypedDict, total=False):
class Filter(TypedDict, total=False):
duration: int
- """Filter by minimum subscription duration in months. Must be at least 0."""
+ """Filter by minimum subscription duration in months.
+
+ Must use bracket syntax: filter[duration]=1 — the dot form (filter.duration=1)
+ is rejected with a 422, because PHP rewrites it to `filter_duration` and the
+ filter could not be applied. Must be at least 0.
+ """
+
+ max_total_spent: float
+ """
+ Filter by **maximum** amount total spent by a fan — use
+ `filter[max_total_spent]=0` to isolate fans who have never spent. Combine with
+ `filter[total_spent]` for a range. Must use bracket syntax:
+ filter[max_total_spent]=0 — the dot form is rejected with a 422, because PHP
+ rewrites it to `filter_max_total_spent` and the filter could not be applied.
+
+ OnlyFans itself has no maximum-spend filter, so this one is resolved against
+ OnlyFansAPI's own fan index instead of being proxied. The fan objects in
+ `data.list` are still fetched live from OnlyFans and are re-checked against your
+ filters before being returned, but only fans we have already indexed for this
+ account can appear. Each response reports its own coverage under `data._source`;
+ when `data._source.is_complete` is `false` a full-base backfill is queued
+ automatically, so retry later for a complete answer.
+
+ `data._source.omitted_from_page` counts fans that matched your filters but which
+ OnlyFans returned no usable data for on that page (a deleted account, or a
+ partial response). They are left out of `data.list` and not revisited later in
+ the same walk, so a non-zero value means that page was short — start a fresh
+ walk to retry them. Cannot be combined with `filter[online]`. Must be at
+ least 0.
+ """
online: Optional[Literal[1, 0]]
- """Filter by online status (`1` for online fans)."""
+ """Filter by online status (`1` for online fans).
+
+ Must use bracket syntax: filter[online]=1 — the dot form (filter.online=1) is
+ rejected with a 422, because PHP rewrites it to `filter_online` and the filter
+ could not be applied.
+ """
tips: int
- """Filter by minimum tips. Must be at least 0."""
+ """Filter by minimum tips.
+
+ Must use bracket syntax: filter[tips]=100 — the dot form (filter.tips=100) is
+ rejected with a 422, because PHP rewrites it to `filter_tips` and the filter
+ could not be applied. Must be at least 0.
+ """
total_spent: int
- """Filter by minimum amount total spent by a fan. Must be at least 0."""
+ """Filter by minimum amount total spent by a fan.
+
+ Must use bracket syntax: filter[total_spent]=100 — the dot form
+ (filter.total_spent=100) is rejected with a 422, because PHP rewrites it to
+ `filter_total_spent` and the filter could not be applied. Must be at least 0.
+ """
diff --git a/src/onlyfansapi/types/fan_list_latest_params.py b/src/onlyfansapi/types/fan_list_latest_params.py
index e56016a8..19b4d08a 100644
--- a/src/onlyfansapi/types/fan_list_latest_params.py
+++ b/src/onlyfansapi/types/fan_list_latest_params.py
@@ -12,13 +12,13 @@ class FanListLatestParams(TypedDict, total=False):
end_date: Optional[str]
"""End date for filtering (required with start_date).
- This field is required when start_date is present.
+ Must be a valid date. Must not be greater than 255 characters.
"""
limit: int
"""Number of fans to return (1-50).
- Must be at least 1. Must not be greater than 100.
+ Must be at least 1. Must not be greater than 50.
"""
offset: int
@@ -27,7 +27,7 @@ class FanListLatestParams(TypedDict, total=False):
start_date: Optional[str]
"""Start date for filtering (required with end_date).
- This field is required when end_date is present.
+ Must be a valid date. Must not be greater than 255 characters.
"""
type: Optional[Literal["total", "renew", "new"]]
diff --git a/src/onlyfansapi/types/fan_list_top_params.py b/src/onlyfansapi/types/fan_list_top_params.py
index 0ba02df0..b4ffb4f2 100644
--- a/src/onlyfansapi/types/fan_list_top_params.py
+++ b/src/onlyfansapi/types/fan_list_top_params.py
@@ -15,11 +15,11 @@ class FanListTopParams(TypedDict, total=False):
end_date: Optional[str]
"""End date for filtering (required with start_date).
- This field is required when start_date is present.
+ Must be a valid date. Must not be greater than 255 characters.
"""
start_date: Optional[str]
"""Start date for filtering (required with end_date).
- This field is required when end_date is present.
+ Must be a valid date. Must not be greater than 255 characters.
"""
diff --git a/src/onlyfansapi/types/fans/summary_get_summary_response.py b/src/onlyfansapi/types/fans/summary_get_summary_response.py
index 13970746..10a718df 100644
--- a/src/onlyfansapi/types/fans/summary_get_summary_response.py
+++ b/src/onlyfansapi/types/fans/summary_get_summary_response.py
@@ -1,15 +1,25 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from ..._models import BaseModel
-__all__ = ["SummaryGetSummaryResponse", "SummaryData"]
+__all__ = ["SummaryGetSummaryResponse", "CustomField", "SummaryData"]
+
+
+class CustomField(BaseModel):
+ key: Optional[str] = None
+
+ label: Optional[str] = None
class SummaryData(BaseModel):
+ content_dislikes: Optional[str] = None
+
content_preferences: Optional[str] = None
+ dos_and_donts: Optional[str] = None
+
family_pets: Optional[str] = None
hobbies: Optional[str] = None
@@ -26,6 +36,8 @@ class SummaryData(BaseModel):
requests: Optional[str] = None
+ spend_cadence: Optional[str] = None
+
themes: Optional[str] = None
travel_plans: Optional[str] = None
@@ -34,10 +46,14 @@ class SummaryData(BaseModel):
class SummaryGetSummaryResponse(BaseModel):
analyzed_message_count: Optional[int] = None
+ custom_fields: Optional[List[CustomField]] = None
+
error_message: Optional[str] = None
last_analyzed_at: Optional[str] = None
+ last_buy_date: Optional[str] = None
+
status: Optional[str] = None
summary_data: Optional[SummaryData] = None
diff --git a/src/onlyfansapi/types/following_list_active_params.py b/src/onlyfansapi/types/following_list_active_params.py
index 3b609c2e..daca43d1 100644
--- a/src/onlyfansapi/types/following_list_active_params.py
+++ b/src/onlyfansapi/types/following_list_active_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
+
+from .._utils import PropertyInfo
__all__ = ["FollowingListActiveParams", "Filter"]
@@ -23,6 +25,36 @@ class FollowingListActiveParams(TypedDict, total=False):
query: Optional[str]
"""Search within following name/username."""
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]]
+ """
+ Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+ """
+
+ sort_direction: Annotated[Optional[Literal["asc", "desc"]], PropertyInfo(alias="sortDirection")]
+ """Direction for `sort`: `desc` (default) or `asc`.
+
+ Requires `sort` to be set. Exception: `sort=expire_date` on the expired list
+ defaults to `asc`, because `desc` moves the expired rows to the tail of the
+ underlying collection and leaves the early pages empty. Passing `sortDirection`
+ explicitly always wins.
+ """
+
class Filter(TypedDict, total=False):
online: Optional[Literal[1, 0]]
diff --git a/src/onlyfansapi/types/following_list_all_params.py b/src/onlyfansapi/types/following_list_all_params.py
index 8016b3f8..cb0a25e0 100644
--- a/src/onlyfansapi/types/following_list_all_params.py
+++ b/src/onlyfansapi/types/following_list_all_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
+
+from .._utils import PropertyInfo
__all__ = ["FollowingListAllParams", "Filter"]
@@ -23,6 +25,36 @@ class FollowingListAllParams(TypedDict, total=False):
query: Optional[str]
"""Search within following name/username."""
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]]
+ """
+ Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+ """
+
+ sort_direction: Annotated[Optional[Literal["asc", "desc"]], PropertyInfo(alias="sortDirection")]
+ """Direction for `sort`: `desc` (default) or `asc`.
+
+ Requires `sort` to be set. Exception: `sort=expire_date` on the expired list
+ defaults to `asc`, because `desc` moves the expired rows to the tail of the
+ underlying collection and leaves the early pages empty. Passing `sortDirection`
+ explicitly always wins.
+ """
+
class Filter(TypedDict, total=False):
online: Optional[Literal[1, 0]]
diff --git a/src/onlyfansapi/types/following_list_expired_params.py b/src/onlyfansapi/types/following_list_expired_params.py
index a3ac1f99..4c5b3771 100644
--- a/src/onlyfansapi/types/following_list_expired_params.py
+++ b/src/onlyfansapi/types/following_list_expired_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
+
+from .._utils import PropertyInfo
__all__ = ["FollowingListExpiredParams", "Filter"]
@@ -23,6 +25,36 @@ class FollowingListExpiredParams(TypedDict, total=False):
query: Optional[str]
"""Search within following name/username."""
+ sort: Optional[Literal["last_activity", "expire_date", "subscribe_date", "is_expired"]]
+ """
+ Order the list by `last_activity` (the followed creator's last activity),
+ `expire_date` (subscription expiry), `subscribe_date` (subscription start) or
+ `is_expired` (expired first — OnlyFans only offers this one on the expired
+ list). Omit it to keep whichever order is currently stored for the account.
+ **Note:** OnlyFans persists this order account-wide, so it also applies to later
+ requests that omit `sort` and to the creator's own onlyfans.com UI, until it is
+ changed again. **Expired list:** OnlyFans applies `offset` to the whole
+ following collection and only then filters it down to expired subscriptions, so
+ ordering by expiry descending puts the still-active subscriptions first and
+ moves the expired rows to the tail of the collection — the first several hundred
+ offsets then come back empty. Use `sortDirection=asc` or `sort=is_expired` to
+ get expired-first results. For that reason `sort=expire_date` on the expired
+ list defaults to `asc` instead of `desc` when you do not pass `sortDirection`.
+ Whatever order you pick, an empty page is **not** the end of the list: keep
+ following `_pagination.next_page` until it is `null` rather than stopping at the
+ first empty page. This field is required when sortDirection is
+ present.
+ """
+
+ sort_direction: Annotated[Optional[Literal["asc", "desc"]], PropertyInfo(alias="sortDirection")]
+ """Direction for `sort`: `desc` (default) or `asc`.
+
+ Requires `sort` to be set. Exception: `sort=expire_date` on the expired list
+ defaults to `asc`, because `desc` moves the expired rows to the tail of the
+ underlying collection and leaves the early pages empty. Passing `sortDirection`
+ explicitly always wins.
+ """
+
class Filter(TypedDict, total=False):
online: Optional[Literal[1, 0]]
diff --git a/src/onlyfansapi/types/link_tag_list_params.py b/src/onlyfansapi/types/link_tag_list_params.py
index 5e15ebb3..32f06094 100644
--- a/src/onlyfansapi/types/link_tag_list_params.py
+++ b/src/onlyfansapi/types/link_tag_list_params.py
@@ -8,5 +8,5 @@
class LinkTagListParams(TypedDict, total=False):
- type: Literal["trial_links", "tracking_links"]
- """Filter by link type. If not provided, returns tags for both types."""
+ type: Literal["trial_links", "tracking_links", "smart_links"]
+ """Filter by link type. If not provided, returns tags for all types."""
diff --git a/src/onlyfansapi/types/mass_messaging_retrieve_overview_params.py b/src/onlyfansapi/types/mass_messaging_retrieve_overview_params.py
index 7e0f386c..775e8fdb 100644
--- a/src/onlyfansapi/types/mass_messaging_retrieve_overview_params.py
+++ b/src/onlyfansapi/types/mass_messaging_retrieve_overview_params.py
@@ -13,7 +13,7 @@ class MassMessagingRetrieveOverviewParams(TypedDict, total=False):
end_date: Annotated[str, PropertyInfo(alias="endDate")]
"""The latest mass message to retrieve.
- Keep empty to get all. MUST BE DATE AFTER `startDate`. This is also used for
+ Keep empty to get all. It must be after `startDate` and is also used for
pagination.
"""
diff --git a/src/onlyfansapi/types/mass_messaging_send_params.py b/src/onlyfansapi/types/mass_messaging_send_params.py
index c49a5c18..93fec255 100644
--- a/src/onlyfansapi/types/mass_messaging_send_params.py
+++ b/src/onlyfansapi/types/mass_messaging_send_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Iterable
-from typing_extensions import Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
@@ -15,6 +15,16 @@ class MassMessagingSendParams(TypedDict, total=False):
text: Required[str]
"""The message text content"""
+ block_banned_words: Annotated[
+ Literal["strict_ban", "risky", "replace_soften"], PropertyInfo(alias="blockBannedWords")
+ ]
+ """
+ Screen `text` for OnlyFans banned words and block the send if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+ """
+
excluded_lists: Annotated[SequenceNotStr[str], PropertyInfo(alias="excludedLists")]
"""Array of user list IDs that the mass message will NOT be sent to."""
@@ -40,8 +50,8 @@ class MassMessagingSendParams(TypedDict, total=False):
provided.
"""
- price: int
- """Price for paid content (0 or between 3-200).
+ price: float
+ """Price for paid content in USD (0 or between 3-200).
In case this is not zero, **mediaFiles** is required
"""
diff --git a/src/onlyfansapi/types/mass_messaging_update_params.py b/src/onlyfansapi/types/mass_messaging_update_params.py
index 70624b78..267e9b26 100644
--- a/src/onlyfansapi/types/mass_messaging_update_params.py
+++ b/src/onlyfansapi/types/mass_messaging_update_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
@@ -16,6 +16,16 @@ class MassMessagingUpdateParams(TypedDict, total=False):
text: Required[str]
"""The message text content"""
+ block_banned_words: Annotated[
+ Literal["strict_ban", "risky", "replace_soften"], PropertyInfo(alias="blockBannedWords")
+ ]
+ """
+ Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+ """
+
giphy_id: Annotated[str, PropertyInfo(alias="giphyId")]
"""The ID of the Giphy GIF to attach to the message.
@@ -38,8 +48,8 @@ class MassMessagingUpdateParams(TypedDict, total=False):
exist in the `mediaFiles` array.
"""
- price: int
- """Price for paid content (0 or between 3-200).
+ price: float
+ """Price for paid content in USD (0 or between 3-200).
In case this is not zero, **mediaFiles** is required
"""
diff --git a/src/onlyfansapi/types/media/vault/__init__.py b/src/onlyfansapi/types/media/vault/__init__.py
index 87e91afe..1335bbc4 100644
--- a/src/onlyfansapi/types/media/vault/__init__.py
+++ b/src/onlyfansapi/types/media/vault/__init__.py
@@ -5,6 +5,7 @@
from .list_list_params import ListListParams as ListListParams
from .list_create_params import ListCreateParams as ListCreateParams
from .list_list_response import ListListResponse as ListListResponse
+from .list_update_params import ListUpdateParams as ListUpdateParams
from .list_create_response import ListCreateResponse as ListCreateResponse
from .list_delete_response import ListDeleteResponse as ListDeleteResponse
from .list_update_response import ListUpdateResponse as ListUpdateResponse
diff --git a/src/onlyfansapi/types/media/vault/list_list_params.py b/src/onlyfansapi/types/media/vault/list_list_params.py
index 43887be9..affafb44 100644
--- a/src/onlyfansapi/types/media/vault/list_list_params.py
+++ b/src/onlyfansapi/types/media/vault/list_list_params.py
@@ -8,6 +8,13 @@
class ListListParams(TypedDict, total=False):
+ lightweight: bool
+ """
+ Set to `true` to return only `id`, `name`, `type`, `canUpdate` and a rolled-up
+ `mediaCount` per list, dropping the `medias` previews. Much smaller payload —
+ ideal for rendering a folder picker. Default: `false`
+ """
+
limit: int
"""Number of media to return per page. Default: `24`"""
diff --git a/src/onlyfansapi/types/media/vault/list_list_response.py b/src/onlyfansapi/types/media/vault/list_list_response.py
index 4af848db..82b97043 100644
--- a/src/onlyfansapi/types/media/vault/list_list_response.py
+++ b/src/onlyfansapi/types/media/vault/list_list_response.py
@@ -1,6 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
+from typing import List, Union, Optional
+from typing_extensions import TypeAlias
from pydantic import Field as FieldInfo
@@ -8,24 +9,33 @@
__all__ = [
"ListListResponse",
- "_Meta",
- "_Meta_Cache",
- "_Meta_Credits",
- "_Meta_RateLimits",
- "Data",
- "DataAll",
- "DataAllMedia",
- "DataList",
+ "UnionMember0",
+ "UnionMember0_Meta",
+ "UnionMember0_Meta_Cache",
+ "UnionMember0_Meta_Credits",
+ "UnionMember0_Meta_RateLimits",
+ "UnionMember0Data",
+ "UnionMember0DataAll",
+ "UnionMember0DataAllMedia",
+ "UnionMember0DataList",
+ "UnionMember1",
+ "UnionMember1_Meta",
+ "UnionMember1_Meta_Cache",
+ "UnionMember1_Meta_Credits",
+ "UnionMember1_Meta_RateLimits",
+ "UnionMember1Data",
+ "UnionMember1DataAll",
+ "UnionMember1DataList",
]
-class _Meta_Cache(BaseModel):
+class UnionMember0_Meta_Cache(BaseModel):
is_cached: Optional[bool] = None
note: Optional[str] = None
-class _Meta_Credits(BaseModel):
+class UnionMember0_Meta_Credits(BaseModel):
balance: Optional[int] = None
note: Optional[str] = None
@@ -33,7 +43,7 @@ class _Meta_Credits(BaseModel):
used: Optional[int] = None
-class _Meta_RateLimits(BaseModel):
+class UnionMember0_Meta_RateLimits(BaseModel):
limit_day: Optional[int] = None
limit_minute: Optional[int] = None
@@ -43,33 +53,33 @@ class _Meta_RateLimits(BaseModel):
remaining_minute: Optional[int] = None
-class _Meta(BaseModel):
- api_cache: Optional[_Meta_Cache] = FieldInfo(alias="_cache", default=None)
+class UnionMember0_Meta(BaseModel):
+ api_cache: Optional[UnionMember0_Meta_Cache] = FieldInfo(alias="_cache", default=None)
- api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+ api_credits: Optional[UnionMember0_Meta_Credits] = FieldInfo(alias="_credits", default=None)
- api_rate_limits: Optional[_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
+ api_rate_limits: Optional[UnionMember0_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
-class DataAllMedia(BaseModel):
+class UnionMember0DataAllMedia(BaseModel):
type: Optional[str] = None
url: Optional[str] = None
-class DataAll(BaseModel):
+class UnionMember0DataAll(BaseModel):
audios_count: Optional[int] = FieldInfo(alias="audiosCount", default=None)
gifs_count: Optional[int] = FieldInfo(alias="gifsCount", default=None)
- medias: Optional[List[DataAllMedia]] = None
+ medias: Optional[List[UnionMember0DataAllMedia]] = None
photos_count: Optional[int] = FieldInfo(alias="photosCount", default=None)
videos_count: Optional[int] = FieldInfo(alias="videosCount", default=None)
-class DataList(BaseModel):
+class UnionMember0DataList(BaseModel):
id: Optional[int] = None
audios_count: Optional[int] = FieldInfo(alias="audiosCount", default=None)
@@ -93,21 +103,96 @@ class DataList(BaseModel):
videos_count: Optional[int] = FieldInfo(alias="videosCount", default=None)
-class Data(BaseModel):
- all: Optional[DataAll] = None
+class UnionMember0Data(BaseModel):
+ all: Optional[UnionMember0DataAll] = None
can_create_vault_lists: Optional[bool] = FieldInfo(alias="canCreateVaultLists", default=None)
has_more: Optional[bool] = FieldInfo(alias="hasMore", default=None)
- list: Optional[List[DataList]] = None
+ list: Optional[List[UnionMember0DataList]] = None
order: Optional[str] = None
sort: Optional[str] = None
-class ListListResponse(BaseModel):
- api_meta: Optional[_Meta] = FieldInfo(alias="_meta", default=None)
+class UnionMember0(BaseModel):
+ """Success"""
- data: Optional[Data] = None
+ api_meta: Optional[UnionMember0_Meta] = FieldInfo(alias="_meta", default=None)
+
+ data: Optional[UnionMember0Data] = None
+
+
+class UnionMember1_Meta_Cache(BaseModel):
+ is_cached: Optional[bool] = None
+
+ note: Optional[str] = None
+
+
+class UnionMember1_Meta_Credits(BaseModel):
+ balance: Optional[int] = None
+
+ note: Optional[str] = None
+
+ used: Optional[int] = None
+
+
+class UnionMember1_Meta_RateLimits(BaseModel):
+ limit_day: Optional[int] = None
+
+ limit_minute: Optional[int] = None
+
+ remaining_day: Optional[int] = None
+
+ remaining_minute: Optional[int] = None
+
+
+class UnionMember1_Meta(BaseModel):
+ api_cache: Optional[UnionMember1_Meta_Cache] = FieldInfo(alias="_cache", default=None)
+
+ api_credits: Optional[UnionMember1_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+
+ api_rate_limits: Optional[UnionMember1_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
+
+
+class UnionMember1DataAll(BaseModel):
+ media_count: Optional[int] = FieldInfo(alias="mediaCount", default=None)
+
+
+class UnionMember1DataList(BaseModel):
+ id: Optional[int] = None
+
+ can_update: Optional[bool] = FieldInfo(alias="canUpdate", default=None)
+
+ media_count: Optional[int] = FieldInfo(alias="mediaCount", default=None)
+
+ name: Optional[str] = None
+
+ type: Optional[str] = None
+
+
+class UnionMember1Data(BaseModel):
+ all: Optional[UnionMember1DataAll] = None
+
+ can_create_vault_lists: Optional[bool] = FieldInfo(alias="canCreateVaultLists", default=None)
+
+ has_more: Optional[bool] = FieldInfo(alias="hasMore", default=None)
+
+ list: Optional[List[UnionMember1DataList]] = None
+
+ order: Optional[str] = None
+
+ sort: Optional[str] = None
+
+
+class UnionMember1(BaseModel):
+ """Success (lightweight=true)"""
+
+ api_meta: Optional[UnionMember1_Meta] = FieldInfo(alias="_meta", default=None)
+
+ data: Optional[UnionMember1Data] = None
+
+
+ListListResponse: TypeAlias = Union[UnionMember0, UnionMember1]
diff --git a/src/onlyfansapi/types/media/vault/list_update_params.py b/src/onlyfansapi/types/media/vault/list_update_params.py
new file mode 100644
index 00000000..1e8190f3
--- /dev/null
+++ b/src/onlyfansapi/types/media/vault/list_update_params.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ListUpdateParams"]
+
+
+class ListUpdateParams(TypedDict, total=False):
+ account: Required[str]
+
+ name: Required[str]
+ """The new name for the vault list. Must not be greater than 255 characters."""
diff --git a/src/onlyfansapi/types/media/vault_upload_params.py b/src/onlyfansapi/types/media/vault_upload_params.py
index d4510143..b69893db 100644
--- a/src/onlyfansapi/types/media/vault_upload_params.py
+++ b/src/onlyfansapi/types/media/vault_upload_params.py
@@ -14,7 +14,9 @@ class VaultUploadParams(TypedDict, total=False):
async_: Annotated[bool, PropertyInfo(alias="async")]
"""Set to `true` to process uploads in the background.
- Returns a `polling_url` to check status. Recommended for large files.
+ Returns a `polling_url` to check status. Recommended for large files. Instead of
+ polling, you can subscribe to the `media_uploads.completed` and
+ `media_uploads.failed` webhook events — they only fire for async uploads.
"""
file: FileTypes
diff --git a/src/onlyfansapi/types/media_download_response.py b/src/onlyfansapi/types/media_download_response.py
deleted file mode 100644
index 8b95a306..00000000
--- a/src/onlyfansapi/types/media_download_response.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import TypeAlias
-
-__all__ = ["MediaDownloadResponse"]
-
-MediaDownloadResponse: TypeAlias = str
diff --git a/src/onlyfansapi/types/media_upload_params.py b/src/onlyfansapi/types/media_upload_params.py
index f663c72e..b32b35c5 100644
--- a/src/onlyfansapi/types/media_upload_params.py
+++ b/src/onlyfansapi/types/media_upload_params.py
@@ -14,7 +14,9 @@ class MediaUploadParams(TypedDict, total=False):
async_: Annotated[bool, PropertyInfo(alias="async")]
"""Set to `true` to process uploads in the background.
- Returns a `polling_url` to check status. Recommended for large files.
+ Returns a `polling_url` to check status. Recommended for large files. Instead of
+ polling, you can subscribe to the `media_uploads.completed` and
+ `media_uploads.failed` webhook events — they only fire for async uploads.
"""
file: FileTypes
diff --git a/src/onlyfansapi/types/message_attach_tags_params.py b/src/onlyfansapi/types/message_attach_tags_params.py
deleted file mode 100644
index 3857488d..00000000
--- a/src/onlyfansapi/types/message_attach_tags_params.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["MessageAttachTagsParams"]
-
-
-class MessageAttachTagsParams(TypedDict, total=False):
- account: Required[str]
-
- rf_guest: Annotated[str, PropertyInfo(alias="rfGuest")]
- """Array of OnlyFans Release Form Guest IDs to tag in your message"""
-
- rf_partner: Annotated[str, PropertyInfo(alias="rfPartner")]
- """Array of OnlyFans Release Form Partners IDs to tag in your message"""
-
- rf_tag: Annotated[str, PropertyInfo(alias="rfTag")]
- """Array of OnlyFans Creator User IDs to tag in your message"""
diff --git a/src/onlyfansapi/types/message_attach_tags_response.py b/src/onlyfansapi/types/message_attach_tags_response.py
deleted file mode 100644
index 21d7fe86..00000000
--- a/src/onlyfansapi/types/message_attach_tags_response.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-
-__all__ = ["MessageAttachTagsResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "_Meta_RateLimits", "Data"]
-
-
-class _Meta_Cache(BaseModel):
- is_cached: Optional[bool] = None
-
- note: Optional[str] = None
-
-
-class _Meta_Credits(BaseModel):
- balance: Optional[int] = None
-
- note: Optional[str] = None
-
- used: Optional[int] = None
-
-
-class _Meta_RateLimits(BaseModel):
- limit_day: Optional[int] = None
-
- limit_minute: Optional[int] = None
-
- remaining_day: Optional[int] = None
-
- remaining_minute: Optional[int] = None
-
-
-class _Meta(BaseModel):
- api_cache: Optional[_Meta_Cache] = FieldInfo(alias="_cache", default=None)
-
- api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
-
- api_rate_limits: Optional[_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
-
-
-class Data(BaseModel):
- success: Optional[bool] = None
-
-
-class MessageAttachTagsResponse(BaseModel):
- api_meta: Optional[_Meta] = FieldInfo(alias="_meta", default=None)
-
- data: Optional[Data] = None
diff --git a/src/onlyfansapi/types/notification_list_params.py b/src/onlyfansapi/types/notification_list_params.py
index b9aeb0aa..78e69bc9 100644
--- a/src/onlyfansapi/types/notification_list_params.py
+++ b/src/onlyfansapi/types/notification_list_params.py
@@ -18,7 +18,7 @@ class NotificationListParams(TypedDict, total=False):
"""The number of notifications. Default `10`"""
skip_users: Literal["all", "none"]
- """Whether to skip user details. Default `all`"""
+ """Whether to skip user details. Defaults to `all`."""
type: Literal[
"all", "subscriptions", "onlyfans", "purchases", "tips", "tags", "comments", "mentions", "likes", "promotions"
diff --git a/src/onlyfansapi/types/post_create_params.py b/src/onlyfansapi/types/post_create_params.py
index 69af87fc..879857b7 100644
--- a/src/onlyfansapi/types/post_create_params.py
+++ b/src/onlyfansapi/types/post_create_params.py
@@ -15,6 +15,16 @@ class PostCreateParams(TypedDict, total=False):
text: Required[str]
"""The post text content"""
+ block_banned_words: Annotated[
+ Literal["strict_ban", "risky", "replace_soften"], PropertyInfo(alias="blockBannedWords")
+ ]
+ """
+ Screen `text` for OnlyFans banned words and block the post if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+ """
+
expire_days: Annotated[int, PropertyInfo(alias="expireDays")]
"""Number of days after which the post will expire.
diff --git a/src/onlyfansapi/types/post_update_params.py b/src/onlyfansapi/types/post_update_params.py
index 0e647cf5..8dbef203 100644
--- a/src/onlyfansapi/types/post_update_params.py
+++ b/src/onlyfansapi/types/post_update_params.py
@@ -16,6 +16,16 @@ class PostUpdateParams(TypedDict, total=False):
text: Required[str]
"""The post text content"""
+ block_banned_words: Annotated[
+ Literal["strict_ban", "risky", "replace_soften"], PropertyInfo(alias="blockBannedWords")
+ ]
+ """
+ Screen `text` for OnlyFans banned words and block the update if any are found
+ (returns a 422 listing the offending words). `strict_ban` blocks all tiers,
+ `risky` blocks Risky + Replace/soften, `replace_soften` blocks Replace/soften
+ only. Omit to disable screening.
+ """
+
expire_days: Annotated[int, PropertyInfo(alias="expireDays")]
"""Number of days after which the post will expire.
diff --git a/src/onlyfansapi/types/queue_list_params.py b/src/onlyfansapi/types/queue_list_params.py
index 93bd08f1..dab6b00b 100644
--- a/src/onlyfansapi/types/queue_list_params.py
+++ b/src/onlyfansapi/types/queue_list_params.py
@@ -2,7 +2,8 @@
from __future__ import annotations
-from typing_extensions import Required, Annotated, TypedDict
+from typing import List
+from typing_extensions import Literal, Required, Annotated, TypedDict
from .._utils import PropertyInfo
@@ -10,17 +11,31 @@
class QueueListParams(TypedDict, total=False):
- limit: Required[int]
- """Maximum number of queue items to return (default = 20)"""
-
publish_date_end: Required[Annotated[str, PropertyInfo(alias="publishDateEnd")]]
- """Latest publish date to return"""
+ """Latest publish date to return.
+
+ Must be a valid date. Must be a valid date. Must be a date after or equal to
+ publishDateStart.
+ """
publish_date_start: Required[Annotated[str, PropertyInfo(alias="publishDateStart")]]
- """Earliest publish date to return (must be at least today)"""
+ """Earliest publish date to return (must be at least today).
+
+ Must be a valid date. Must be a valid date. Must be a date after or equal to
+ today.
+ """
timezone: Required[str]
- """Time timezone of the provided dates.
+ """Timezone of the provided dates.
- [View available timezone values](https://www.php.net/manual/en/timezones.php)
+ [View available timezone values](https://www.php.net/manual/en/timezones.php).
+ Must be a valid time zone, such as Africa/Accra.
"""
+
+ limit: int
+ """Maximum number of queue items to return (default 20).
+
+ Must be at least 1. Must not be greater than 100.
+ """
+
+ type: List[Literal["chat", "post"]]
diff --git a/src/onlyfansapi/types/release_form_list_taggable_users_response.py b/src/onlyfansapi/types/release_form_list_taggable_users_response.py
index 5317664a..0bcb18a5 100644
--- a/src/onlyfansapi/types/release_form_list_taggable_users_response.py
+++ b/src/onlyfansapi/types/release_form_list_taggable_users_response.py
@@ -55,6 +55,8 @@ class _Meta(BaseModel):
class _Pagination(BaseModel):
next_page: Optional[str] = None
+ notice: Optional[str] = None
+
class DataItemUserAvatarThumbs(BaseModel):
c144: Optional[str] = None
@@ -95,8 +97,6 @@ class DataItem(BaseModel):
class Data(BaseModel):
- has_more: Optional[bool] = FieldInfo(alias="hasMore", default=None)
-
items: Optional[List[DataItem]] = None
diff --git a/src/onlyfansapi/types/shared_tracking_link_list_params.py b/src/onlyfansapi/types/shared_tracking_link_list_params.py
index aab7e30d..74d77314 100644
--- a/src/onlyfansapi/types/shared_tracking_link_list_params.py
+++ b/src/onlyfansapi/types/shared_tracking_link_list_params.py
@@ -2,21 +2,35 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["SharedTrackingLinkListParams"]
class SharedTrackingLinkListParams(TypedDict, total=False):
limit: int
- """The number of shared tracking links to return. Default `10`"""
+ """The number of shared tracking links to return.
+
+ Default `10`. Must be at least 1. Must not be greater than 100.
+ """
offset: int
- """The offset used for pagination. Default `0`"""
+ """The offset used for pagination. Default `0`. Must be at least 0."""
+
+ pagination: Literal[0, 1]
+ """Whether pagination metadata is enabled. Default `1`."""
- synchronous: Optional[bool]
- """Wait for the database sync to finish, instead of running it in the background.
+ sorting_deleted: Literal[0, 1]
+ """Whether deleted links participate in sorting. Default `1`."""
- **Will result in longer response times, use with caution**. Default `false`
+ stats: str
+ """Whether statistics are included.
+
+ Default `true`. Must not be greater than 10 characters.
"""
+
+ synchronous: bool
+ """Wait for the database sync instead of processing it in the background."""
+
+ with_deleted: Literal[0, 1]
+ """Whether to include deleted shared tracking links. Default `1`."""
diff --git a/src/onlyfansapi/types/shared_trial_link_list_params.py b/src/onlyfansapi/types/shared_trial_link_list_params.py
index 42de281a..a387a367 100644
--- a/src/onlyfansapi/types/shared_trial_link_list_params.py
+++ b/src/onlyfansapi/types/shared_trial_link_list_params.py
@@ -2,21 +2,22 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["SharedTrialLinkListParams"]
class SharedTrialLinkListParams(TypedDict, total=False):
limit: int
- """The number of shared trial links to return. Default `10`"""
+ """The number of shared trial links to return.
+
+ Default `10`. Must be at least 1. Must not be greater than 100.
+ """
offset: int
- """The offset used for pagination. Default `0`"""
+ """The offset used for pagination. Default `0`. Must be at least 0."""
- synchronous: Optional[bool]
- """Wait for the database sync to finish, instead of running it in the background.
+ pagination: Literal[0, 1]
- **Will result in longer response times, use with caution**. Default `false`
- """
+ synchronous: bool
+ """Wait for the database sync instead of processing it in the background."""
diff --git a/src/onlyfansapi/types/smart_link_list_conversions_params.py b/src/onlyfansapi/types/smart_link_list_conversions_params.py
index 671c1455..b0ddfb5b 100644
--- a/src/onlyfansapi/types/smart_link_list_conversions_params.py
+++ b/src/onlyfansapi/types/smart_link_list_conversions_params.py
@@ -8,7 +8,9 @@
class SmartLinkListConversionsParams(TypedDict, total=False):
- conversion_type: Literal["new_subscriber", "new_transaction", "message_received", "fan_sent_3_messages"]
+ conversion_type: Literal[
+ "new_subscriber", "new_transaction", "message_received", "fan_sent_1_message", "fan_sent_3_messages"
+ ]
"""Optional conversion type filter"""
date_end: str
diff --git a/src/onlyfansapi/types/smart_link_list_fans_params.py b/src/onlyfansapi/types/smart_link_list_fans_params.py
index 28d9ab53..13f4075b 100644
--- a/src/onlyfansapi/types/smart_link_list_fans_params.py
+++ b/src/onlyfansapi/types/smart_link_list_fans_params.py
@@ -26,6 +26,12 @@ class SmartLinkListFansParams(TypedDict, total=False):
offset: int
"""Offset for pagination. Default `0`"""
+ previously_subscribed: bool
+ """
+ Optional - Filter to returning subscribers (fans previously subscribed before
+ this subscription)
+ """
+
sort: Literal[
"revenue_net",
"-revenue_net",
@@ -37,3 +43,6 @@ class SmartLinkListFansParams(TypedDict, total=False):
"-converted_at",
]
"""Optional sort field. Default `-revenue_net`"""
+
+ subscribed_using_promo: bool
+ """Optional - Filter to fans who subscribed via a promotion/offer"""
diff --git a/src/onlyfansapi/types/smart_link_list_fans_response.py b/src/onlyfansapi/types/smart_link_list_fans_response.py
index 89d44bc6..4074d4d2 100644
--- a/src/onlyfansapi/types/smart_link_list_fans_response.py
+++ b/src/onlyfansapi/types/smart_link_list_fans_response.py
@@ -14,6 +14,8 @@
"Data",
"DataFilters",
"DataRow",
+ "DataRowSubscriptionInsights",
+ "DataRowSubscriptionInsightsCurrentSubscription",
"DataSummary",
]
@@ -51,8 +53,36 @@ class DataFilters(BaseModel):
offset: Optional[int] = None
+ previously_subscribed: Optional[str] = None
+
sort: Optional[str] = None
+ subscribed_using_promo: Optional[str] = None
+
+
+class DataRowSubscriptionInsightsCurrentSubscription(BaseModel):
+ action: Optional[str] = None
+
+ is_free: Optional[bool] = None
+
+ price: Optional[int] = None
+
+ regular_price: Optional[int] = None
+
+ type: Optional[str] = None
+
+
+class DataRowSubscriptionInsights(BaseModel):
+ current_subscription: Optional[DataRowSubscriptionInsightsCurrentSubscription] = None
+
+ current_subscription_from_smart_link: Optional[bool] = None
+
+ has_subscription_data: Optional[bool] = None
+
+ previously_subscribed: Optional[bool] = None
+
+ subscribed_using_promo: Optional[bool] = None
+
class DataRow(BaseModel):
avatar_url: Optional[str] = None
@@ -75,6 +105,8 @@ class DataRow(BaseModel):
revenue_net: Optional[int] = None
+ subscription_insights: Optional[DataRowSubscriptionInsights] = None
+
tips_net: Optional[int] = None
username: Optional[str] = None
@@ -83,6 +115,8 @@ class DataRow(BaseModel):
class DataSummary(BaseModel):
fans_total: Optional[int] = None
+ fans_with_1_plus_messages_total: Optional[int] = None
+
fans_with_3_plus_messages_total: Optional[int] = None
revenue_net_total: Optional[int] = None
diff --git a/src/onlyfansapi/types/smart_link_list_params.py b/src/onlyfansapi/types/smart_link_list_params.py
index ca28e0e2..eb0e6f7a 100644
--- a/src/onlyfansapi/types/smart_link_list_params.py
+++ b/src/onlyfansapi/types/smart_link_list_params.py
@@ -5,24 +5,33 @@
from typing import Optional
from typing_extensions import TypedDict
-__all__ = ["SmartLinkListParams"]
+from .._types import SequenceNotStr
+
+__all__ = ["SmartLinkListParams", "Filter"]
class SmartLinkListParams(TypedDict, total=False):
account_ids: Optional[str]
"""Comma-separated account prefixed IDs to include."""
+ filter: Filter
+
limit: int
"""The number of Smart Links to return.
Default `50`. Must be at least 1. Must not be greater than 1000.
"""
- meta_pixel_ids: Optional[str]
- """Comma-separated Meta Pixel IDs to include."""
-
name: Optional[str]
"""Filter Smart Links by name. Must not be greater than 255 characters."""
offset: int
"""The offset used for pagination. Default `0`. Must be at least 0."""
+
+ pixel_ids: Optional[str]
+ """Comma-separated ad platform Pixel IDs to include."""
+
+
+class Filter(TypedDict, total=False):
+ tags: SequenceNotStr[str]
+ """Must not be greater than 50 characters."""
diff --git a/src/onlyfansapi/types/smart_link_postback_create_params.py b/src/onlyfansapi/types/smart_link_postback_create_params.py
index fb5f0e62..dde8295a 100644
--- a/src/onlyfansapi/types/smart_link_postback_create_params.py
+++ b/src/onlyfansapi/types/smart_link_postback_create_params.py
@@ -2,11 +2,12 @@
from __future__ import annotations
+from typing import Iterable, Optional
from typing_extensions import Literal, Required, TypedDict
from .._types import SequenceNotStr
-__all__ = ["SmartLinkPostbackCreateParams"]
+__all__ = ["SmartLinkPostbackCreateParams", "Header"]
class SmartLinkPostbackCreateParams(TypedDict, total=False):
@@ -22,9 +23,33 @@ class SmartLinkPostbackCreateParams(TypedDict, total=False):
url: Required[str]
"""The destination URL.
- Variables such as `{click_id}`, `{fbclid}`, `{gclid}`, and `{ttclid}` are
- replaced when the postback is dispatched.
+ Variables such as `{external_click_id}`, `{fbclid}`, `{gclid}`, and `{ttclid}`
+ are replaced when the postback is dispatched.
"""
+ body: str
+ """Optional request body template for POST postbacks.
+
+ Variables are replaced when the postback is dispatched.
+ """
+
+ headers: Iterable[Header]
+ """Optional request headers. Header values may include postback variables."""
+
+ http_method: Literal["GET", "POST"]
+ """HTTP method used for the postback request. Defaults to `GET` when omitted."""
+
smart_link_ids: SequenceNotStr[str]
"""Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`."""
+
+
+class Header(TypedDict, total=False):
+ name: Optional[str]
+ """This field is required when headers.\\**.value is present.
+
+ Must match the regex /\\AA[A-Za-z0-9!#$%&'*+.^_`|~-]+\\zz/. Must not be greater than
+ 100 characters.
+ """
+
+ value: Optional[str]
+ """Must not be greater than 2000 characters."""
diff --git a/src/onlyfansapi/types/smart_link_postback_create_response.py b/src/onlyfansapi/types/smart_link_postback_create_response.py
index b6681b19..206fd9ea 100644
--- a/src/onlyfansapi/types/smart_link_postback_create_response.py
+++ b/src/onlyfansapi/types/smart_link_postback_create_response.py
@@ -6,7 +6,7 @@
from .._models import BaseModel
-__all__ = ["SmartLinkPostbackCreateResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "Data"]
+__all__ = ["SmartLinkPostbackCreateResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "Data", "DataHeader"]
class _Meta_Cache(BaseModel):
@@ -29,13 +29,25 @@ class _Meta(BaseModel):
api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+class DataHeader(BaseModel):
+ name: Optional[str] = None
+
+ value: Optional[str] = None
+
+
class Data(BaseModel):
id: Optional[int] = None
+ body: Optional[str] = None
+
conversion_types: Optional[List[str]] = None
created_at: Optional[str] = None
+ headers: Optional[List[DataHeader]] = None
+
+ http_method: Optional[str] = None
+
latest_response: Optional[str] = None
smart_link_ids: Optional[List[object]] = None
diff --git a/src/onlyfansapi/types/smart_link_postback_list_response.py b/src/onlyfansapi/types/smart_link_postback_list_response.py
index 865adf2f..4148792e 100644
--- a/src/onlyfansapi/types/smart_link_postback_list_response.py
+++ b/src/onlyfansapi/types/smart_link_postback_list_response.py
@@ -12,6 +12,7 @@
"_Meta_Cache",
"_Meta_Credits",
"Data",
+ "DataHeader",
"DataLatestResponse",
"DataSmartLink",
]
@@ -37,6 +38,12 @@ class _Meta(BaseModel):
api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+class DataHeader(BaseModel):
+ name: Optional[str] = None
+
+ value: Optional[str] = None
+
+
class DataLatestResponse(BaseModel):
id: Optional[int] = None
@@ -68,10 +75,16 @@ class DataSmartLink(BaseModel):
class Data(BaseModel):
id: Optional[int] = None
+ body: Optional[str] = None
+
conversion_types: Optional[List[str]] = None
created_at: Optional[str] = None
+ headers: Optional[List[DataHeader]] = None
+
+ http_method: Optional[str] = None
+
latest_response: Optional[DataLatestResponse] = None
smart_link_ids: Optional[List[str]] = None
diff --git a/src/onlyfansapi/types/smart_link_postback_retrieve_response.py b/src/onlyfansapi/types/smart_link_postback_retrieve_response.py
index 6eadd6af..33eed376 100644
--- a/src/onlyfansapi/types/smart_link_postback_retrieve_response.py
+++ b/src/onlyfansapi/types/smart_link_postback_retrieve_response.py
@@ -6,7 +6,15 @@
from .._models import BaseModel
-__all__ = ["SmartLinkPostbackRetrieveResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "Data", "DataSmartLink"]
+__all__ = [
+ "SmartLinkPostbackRetrieveResponse",
+ "_Meta",
+ "_Meta_Cache",
+ "_Meta_Credits",
+ "Data",
+ "DataHeader",
+ "DataSmartLink",
+]
class _Meta_Cache(BaseModel):
@@ -29,6 +37,12 @@ class _Meta(BaseModel):
api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+class DataHeader(BaseModel):
+ name: Optional[str] = None
+
+ value: Optional[str] = None
+
+
class DataSmartLink(BaseModel):
account_display_name: Optional[str] = None
@@ -42,10 +56,16 @@ class DataSmartLink(BaseModel):
class Data(BaseModel):
id: Optional[int] = None
+ body: Optional[str] = None
+
conversion_types: Optional[List[str]] = None
created_at: Optional[str] = None
+ headers: Optional[List[DataHeader]] = None
+
+ http_method: Optional[str] = None
+
latest_response: Optional[str] = None
smart_link_ids: Optional[List[str]] = None
diff --git a/src/onlyfansapi/types/smart_link_postback_update_params.py b/src/onlyfansapi/types/smart_link_postback_update_params.py
index 7863cc78..93a1e972 100644
--- a/src/onlyfansapi/types/smart_link_postback_update_params.py
+++ b/src/onlyfansapi/types/smart_link_postback_update_params.py
@@ -2,11 +2,12 @@
from __future__ import annotations
+from typing import Iterable, Optional
from typing_extensions import Literal, Required, TypedDict
from .._types import SequenceNotStr
-__all__ = ["SmartLinkPostbackUpdateParams"]
+__all__ = ["SmartLinkPostbackUpdateParams", "Header"]
class SmartLinkPostbackUpdateParams(TypedDict, total=False):
@@ -19,5 +20,29 @@ class SmartLinkPostbackUpdateParams(TypedDict, total=False):
url: Required[str]
"""The destination URL."""
+ body: str
+ """Optional request body template for POST postbacks.
+
+ Variables are replaced when the postback is dispatched.
+ """
+
+ headers: Iterable[Header]
+ """Optional request headers. Header values may include postback variables."""
+
+ http_method: Literal["GET", "POST"]
+ """HTTP method used for the postback request. Existing value is kept when omitted."""
+
smart_link_ids: SequenceNotStr[str]
"""Smart Link ULIDs. Required when `smart_link_scope` is `campaign_specific`."""
+
+
+class Header(TypedDict, total=False):
+ name: Optional[str]
+ """This field is required when headers.\\**.value is present.
+
+ Must match the regex /\\AA[A-Za-z0-9!#$%&'*+.^_`|~-]+\\zz/. Must not be greater than
+ 100 characters.
+ """
+
+ value: Optional[str]
+ """Must not be greater than 2000 characters."""
diff --git a/src/onlyfansapi/types/smart_link_postback_update_response.py b/src/onlyfansapi/types/smart_link_postback_update_response.py
index fc416c17..018c9516 100644
--- a/src/onlyfansapi/types/smart_link_postback_update_response.py
+++ b/src/onlyfansapi/types/smart_link_postback_update_response.py
@@ -6,7 +6,15 @@
from .._models import BaseModel
-__all__ = ["SmartLinkPostbackUpdateResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "Data", "DataSmartLink"]
+__all__ = [
+ "SmartLinkPostbackUpdateResponse",
+ "_Meta",
+ "_Meta_Cache",
+ "_Meta_Credits",
+ "Data",
+ "DataHeader",
+ "DataSmartLink",
+]
class _Meta_Cache(BaseModel):
@@ -29,6 +37,12 @@ class _Meta(BaseModel):
api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+class DataHeader(BaseModel):
+ name: Optional[str] = None
+
+ value: Optional[str] = None
+
+
class DataSmartLink(BaseModel):
account_display_name: Optional[str] = None
@@ -42,10 +56,16 @@ class DataSmartLink(BaseModel):
class Data(BaseModel):
id: Optional[int] = None
+ body: Optional[str] = None
+
conversion_types: Optional[List[str]] = None
created_at: Optional[str] = None
+ headers: Optional[List[DataHeader]] = None
+
+ http_method: Optional[str] = None
+
latest_response: Optional[str] = None
smart_link_ids: Optional[List[str]] = None
diff --git a/src/onlyfansapi/types/statistic_calculate_total_transactions_params.py b/src/onlyfansapi/types/statistic_calculate_total_transactions_params.py
index 66fa41f1..71ea0b05 100644
--- a/src/onlyfansapi/types/statistic_calculate_total_transactions_params.py
+++ b/src/onlyfansapi/types/statistic_calculate_total_transactions_params.py
@@ -2,14 +2,14 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing_extensions import TypedDict
__all__ = ["StatisticCalculateTotalTransactionsParams"]
class StatisticCalculateTotalTransactionsParams(TypedDict, total=False):
- end_date: Required[str]
+ end_date: str
"""The end date for the period. Keep empty to calculate everything."""
- start_date: Required[str]
+ start_date: str
"""The start date for the period. Keep empty to calculate everything."""
diff --git a/src/onlyfansapi/types/statistic_get_subscriber_metrics_params.py b/src/onlyfansapi/types/statistic_get_subscriber_metrics_params.py
index 9f177238..90a0cd3e 100644
--- a/src/onlyfansapi/types/statistic_get_subscriber_metrics_params.py
+++ b/src/onlyfansapi/types/statistic_get_subscriber_metrics_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
__all__ = ["StatisticGetSubscriberMetricsParams"]
@@ -21,3 +21,9 @@ class StatisticGetSubscriberMetricsParams(TypedDict, total=False):
Will slow down the response time, and might time out if timeframe is too large.
Default = `false`
"""
+
+ detailed_type: Optional[Literal["total", "renew", "new"]]
+ """Use only with `detailed=true` - otherwise, it has no effect.
+
+ Filter the subscriber statistics (default = total)
+ """
diff --git a/src/onlyfansapi/types/statistics/reach_get_profile_visitors_params.py b/src/onlyfansapi/types/statistics/reach_get_profile_visitors_params.py
index 38a62b8e..69bce51b 100644
--- a/src/onlyfansapi/types/statistics/reach_get_profile_visitors_params.py
+++ b/src/onlyfansapi/types/statistics/reach_get_profile_visitors_params.py
@@ -13,7 +13,7 @@ class ReachGetProfileVisitorsParams(TypedDict, total=False):
"""The end date for the period."""
start_date: Required[str]
- """The start date for the period"""
+ """The start date for the period."""
filter: Optional[Literal["chart", "topCountries"]]
"""Optionally, filter the results by `chart` or `topCountries`.
diff --git a/src/onlyfansapi/types/statistics/statement_get_earnings_params.py b/src/onlyfansapi/types/statistics/statement_get_earnings_params.py
index 82acb3cd..d04e5695 100644
--- a/src/onlyfansapi/types/statistics/statement_get_earnings_params.py
+++ b/src/onlyfansapi/types/statistics/statement_get_earnings_params.py
@@ -8,11 +8,11 @@
class StatementGetEarningsParams(TypedDict, total=False):
- start_date: Required[str]
- """The start date for the period"""
-
- end_date: str
+ end_date: Required[str]
"""The end date for the period."""
+ start_date: Required[str]
+ """The start date for the period."""
+
type: Literal["total", "subscribes", "tips", "post", "messages", "stream"]
"""Filter by All / Subscriptions / Tips / Posts / Messages / Streams"""
diff --git a/src/onlyfansapi/types/story_create_params.py b/src/onlyfansapi/types/story_create_params.py
index 77e52aca..5fc7fbb9 100644
--- a/src/onlyfansapi/types/story_create_params.py
+++ b/src/onlyfansapi/types/story_create_params.py
@@ -2,17 +2,121 @@
from __future__ import annotations
-from typing_extensions import Required, Annotated, TypedDict
+from typing import Iterable
+from typing_extensions import Literal, Required, Annotated, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
-__all__ = ["StoryCreateParams"]
+__all__ = ["StoryCreateParams", "Question", "Text"]
class StoryCreateParams(TypedDict, total=False):
media_files: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="mediaFiles")]]
+ """Array of media file upload prefixed_ids, or OF vault media IDs."""
+
+ canvas_height: Annotated[int, PropertyInfo(alias="canvasHeight")]
+ """Canvas height overlay positions are relative to. Default `1920`."""
+
+ canvas_width: Annotated[int, PropertyInfo(alias="canvasWidth")]
+ """Canvas width overlay positions are relative to. Default `1080`."""
+
+ question: Question
+ """Interactive question sticker viewers can answer."""
+
+ texts: Iterable[Text]
+ """Text and @mention overlays."""
+
+
+class Question(TypedDict, total=False):
+ """Interactive question sticker viewers can answer."""
+
+ color: str
+ """Sticker accent color (hex). Default `#FF51DC`."""
+
+ height: float
+ """Sticker height in canvas px. Default `160`."""
+
+ left: float
+ """Horizontal position as a percentage of the canvas width (0-100). Default `25`."""
+
+ text: str
+ """The question to ask."""
+
+ top: float
+ """Vertical position as a percentage of the canvas height (0-100). Default `30`."""
+
+ width: float
+ """Sticker width in canvas px. Default `257`."""
+
+
+class Text(TypedDict, total=False):
+ text: Required[str]
+ """The overlay text.
+
+ For mentions this must be the `@username` to mention (OnlyFans resolves the user
+ and adds them to the story's release forms).
+ """
+
+ angle: float
+ """Rotation in degrees. Default `0`."""
+
+ bg_color: Annotated[str, PropertyInfo(alias="bgColor")]
+ """Background color (hex, `#00000000` = transparent).
+
+ Native editor palette: #FFFFFF #000000 #69818C #FF51DC #FF4081 #FA3240 #FF8040
+ #FCA800 #70CF27 #00C864 #00B1CC #2196F3 #7953F5 #A832BF. Default: transparent
+ for texts, white for mentions.
"""
- Array of media file upload prefixed_ids, or OF media IDs (required if price is
- not 0).
+
+ color: str
+ """Text color (hex).
+
+ Defaults to the native editor behavior: white on a colored background, black on
+ a white background (mentions: OnlyFans blue `#0091EA` on white).
+ """
+
+ font_family: Annotated[
+ Literal["Roboto", "PTMono", "ShantellSans", "SofiaSans", "YanoneKaffeesatz", "RubikMedium", "RubikBlack"],
+ PropertyInfo(alias="fontFamily"),
+ ]
+ """Font family.
+
+ Families support specific weights only: Roboto (400/500/700), PTMono (400),
+ ShantellSans (400), SofiaSans (400, renders uppercase), YanoneKaffeesatz (700),
+ RubikMedium (500), RubikBlack (700). Default `Roboto`. Ignored for mentions
+ (always Roboto 500).
+ """
+
+ font_size: Annotated[float, PropertyInfo(alias="fontSize")]
+ """Font size in canvas px (8-100). The native editor uses 9-36. Default `20`."""
+
+ font_weight: Annotated[Literal[400, 500, 700], PropertyInfo(alias="fontWeight")]
+ """Font weight; must match the chosen family (see `fontFamily`)."""
+
+ left: float
+ """Horizontal position as a percentage of the canvas width (0-100). Default `25`."""
+
+ scale: float
+ """Scale factor. Default `1`."""
+
+ text_align: Annotated[Literal["left", "center", "right"], PropertyInfo(alias="textAlign")]
+ """Text alignment. Default `left`."""
+
+ text_height: Annotated[float, PropertyInfo(alias="textHeight")]
+ """Rendered text box height in canvas px. Estimated automatically when omitted."""
+
+ text_width: Annotated[float, PropertyInfo(alias="textWidth")]
+ """Rendered text box width in canvas px. Estimated automatically when omitted."""
+
+ top: float
+ """Vertical position as a percentage of the canvas height (0-100).
+
+ Defaults stagger each overlay below the previous one.
"""
+
+ type: Literal["text", "mention"]
+ """Overlay type. Default `text`."""
+
+ z_index: Annotated[int, PropertyInfo(alias="zIndex")]
+ """Stacking order. Defaults to placement order."""
diff --git a/src/onlyfansapi/types/story_create_response.py b/src/onlyfansapi/types/story_create_response.py
index 599c07d9..2cb26954 100644
--- a/src/onlyfansapi/types/story_create_response.py
+++ b/src/onlyfansapi/types/story_create_response.py
@@ -16,6 +16,12 @@
"DataMedia",
"DataMediaFiles",
"DataMediaFilesFull",
+ "DataQuestion",
+ "DataQuestionEntity",
+ "DataQuestionPositions",
+ "DataReleaseForm",
+ "DataReleaseFormUser",
+ "DataText",
]
@@ -97,11 +103,119 @@ class DataMedia(BaseModel):
type: Optional[str] = None
+class DataQuestionEntity(BaseModel):
+ id: Optional[int] = None
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ text: Optional[str] = None
+
+
+class DataQuestionPositions(BaseModel):
+ angle: Optional[int] = None
+
+ color: Optional[str] = None
+
+ height: Optional[int] = None
+
+ left: Optional[int] = None
+
+ top: Optional[int] = None
+
+ width: Optional[int] = None
+
+ x: Optional[str] = None
+
+ y: Optional[str] = None
+
+ z_index: Optional[int] = FieldInfo(alias="zIndex", default=None)
+
+
+class DataQuestion(BaseModel):
+ entity: Optional[DataQuestionEntity] = None
+
+ positions: Optional[DataQuestionPositions] = None
+
+ type: Optional[str] = None
+
+
+class DataReleaseFormUser(BaseModel):
+ id: Optional[int] = None
+
+ avatar: Optional[str] = None
+
+ avatar_thumbs: Optional[str] = FieldInfo(alias="avatarThumbs", default=None)
+
+ is_from_guest: Optional[bool] = FieldInfo(alias="isFromGuest", default=None)
+
+ is_identity_verified: Optional[bool] = FieldInfo(alias="isIdentityVerified", default=None)
+
+ iv_status: Optional[str] = FieldInfo(alias="ivStatus", default=None)
+
+ name: Optional[str] = None
+
+ username: Optional[str] = None
+
+ view: Optional[str] = None
+
+
+class DataReleaseForm(BaseModel):
+ id: Optional[int] = None
+
+ name: Optional[str] = None
+
+ partner_source: Optional[str] = FieldInfo(alias="partnerSource", default=None)
+
+ type: Optional[str] = None
+
+ user: Optional[DataReleaseFormUser] = None
+
+
+class DataText(BaseModel):
+ angle: Optional[int] = None
+
+ bg_color: Optional[str] = FieldInfo(alias="bgColor", default=None)
+
+ color: Optional[str] = None
+
+ font_family: Optional[str] = FieldInfo(alias="fontFamily", default=None)
+
+ font_size: Optional[str] = FieldInfo(alias="fontSize", default=None)
+
+ font_style: Optional[str] = FieldInfo(alias="fontStyle", default=None)
+
+ font_weight: Optional[int] = FieldInfo(alias="fontWeight", default=None)
+
+ left: Optional[int] = None
+
+ scale: Optional[int] = None
+
+ text: Optional[str] = None
+
+ text_align: Optional[str] = FieldInfo(alias="textAlign", default=None)
+
+ text_height: Optional[float] = FieldInfo(alias="textHeight", default=None)
+
+ text_width: Optional[int] = FieldInfo(alias="textWidth", default=None)
+
+ top: Optional[int] = None
+
+ type: Optional[str] = None
+
+ users: Optional[List[object]] = None
+
+ z_index: Optional[int] = FieldInfo(alias="zIndex", default=None)
+
+
class Data(BaseModel):
id: Optional[int] = None
can_delete: Optional[bool] = FieldInfo(alias="canDelete", default=None)
+ canvas_height: Optional[int] = FieldInfo(alias="canvasHeight", default=None)
+
+ canvas_width: Optional[int] = FieldInfo(alias="canvasWidth", default=None)
+
comments_count: Optional[int] = FieldInfo(alias="commentsCount", default=None)
created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
@@ -120,9 +234,11 @@ class Data(BaseModel):
media: Optional[List[DataMedia]] = None
- question: Optional[str] = None
+ question: Optional[DataQuestion] = None
+
+ release_forms: Optional[List[DataReleaseForm]] = FieldInfo(alias="releaseForms", default=None)
- release_forms: Optional[List[object]] = FieldInfo(alias="releaseForms", default=None)
+ texts: Optional[List[DataText]] = None
tips_amount: Optional[str] = FieldInfo(alias="tipsAmount", default=None)
diff --git a/src/onlyfansapi/types/tracking_link_list_params.py b/src/onlyfansapi/types/tracking_link_list_params.py
index da8ad7d6..7b70132b 100644
--- a/src/onlyfansapi/types/tracking_link_list_params.py
+++ b/src/onlyfansapi/types/tracking_link_list_params.py
@@ -12,32 +12,36 @@
class TrackingLinkListParams(TypedDict, total=False):
end_date: Annotated[Optional[str], PropertyInfo(alias="endDate")]
- """The end date for Tracking Links. Keep empty to get all."""
+ """The end date for tracking links.
- limit: Optional[int]
- """The number of tracking links to return. Default `3`"""
+ Keep empty to get all. Must not be greater than 255 characters.
+ """
+
+ limit: int
+ """The number of tracking links to return.
+
+ Default `10`. Must be at least 1. Must not be greater than 100.
+ """
- offset: Optional[int]
- """The offset used for pagination. Default `0`"""
+ offset: int
+ """The offset used for pagination. Default `0`. Must be at least 0."""
- sort: Optional[Literal["desc", "asc"]]
- """Sort the results. Default `desc`"""
+ pagination: Literal[0, 1]
- sortby: Optional[Literal["claims", "created_date"]]
- """Sort by subscriber count (claims), or creation date"""
+ sort: Literal["asc", "desc"]
+ """Sort direction. Default `desc`."""
+
+ sortby: Literal["claims", "created_date"]
+ """Sort by subscriber count (`claims`) or creation date (`created_date`)."""
start_date: Annotated[Optional[str], PropertyInfo(alias="startDate")]
- """The start date for Tracking Links. Keep empty to get all."""
+ """The start date for tracking links.
- synchronous: Optional[bool]
- """
- Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+ Keep empty to get all. Must not be greater than 255 characters.
"""
- with_deleted: Optional[bool]
- """Whether or not to include deleted tracking links in the response.
+ synchronous: bool
+ """Wait for revenue calculation instead of processing it in the background."""
- Default `false`
- """
+ with_deleted: Literal[0, 1]
+ """Whether to include deleted tracking links. Default `true`."""
diff --git a/src/onlyfansapi/types/transaction_list_params.py b/src/onlyfansapi/types/transaction_list_params.py
index 5ac6a989..eca4ac29 100644
--- a/src/onlyfansapi/types/transaction_list_params.py
+++ b/src/onlyfansapi/types/transaction_list_params.py
@@ -17,7 +17,7 @@ class TransactionListParams(TypedDict, total=False):
"""The marker used for pagination. Default: `null`"""
start_date: Annotated[str, PropertyInfo(alias="startDate")]
- """The start date for transactions list. Default: `-30days`"""
+ """The start date for the transactions list. Defaults to 30 days ago."""
tips_source: Annotated[str, PropertyInfo(alias="tipsSource")]
"""Filter tips by source.
diff --git a/src/onlyfansapi/types/trial_link_list_params.py b/src/onlyfansapi/types/trial_link_list_params.py
index 38cd759d..9a6a2dab 100644
--- a/src/onlyfansapi/types/trial_link_list_params.py
+++ b/src/onlyfansapi/types/trial_link_list_params.py
@@ -3,27 +3,40 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
+
+from .._utils import PropertyInfo
__all__ = ["TrialLinkListParams"]
class TrialLinkListParams(TypedDict, total=False):
- limit: Required[int]
- """The number of trial links to return. Default `10`"""
+ end_date: Annotated[Optional[str], PropertyInfo(alias="endDate")]
+ """The end date for trial links.
- offset: Required[int]
- """The offset used for pagination. Default `0`"""
+ Keep empty to get all. Must not be greater than 255 characters.
+ """
- field: Optional[Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]]
- """Sort the results by a field. Default `create_date`"""
+ field: Literal["create_date", "expire_date", "subscribe_counts", "subscribe_days", "claims_count"]
+ """Field to sort by. Default `create_date`."""
- sort: Optional[Literal["desc", "asc"]]
- """Sort the results. Default `desc`"""
+ limit: int
+ """The number of trial links to return.
- synchronous: Optional[bool]
+ Default `10`. Must be at least 1. Must not be greater than 100.
"""
- Wait for the revenue data to finish processing, instead of processing in the
- background. **Will result in longer response times, use with caution**. Default
- `false`
+
+ offset: int
+ """The offset used for pagination. Default `0`. Must be at least 0."""
+
+ sort: Literal["asc", "desc"]
+ """Sort direction. Default `desc`."""
+
+ start_date: Annotated[Optional[str], PropertyInfo(alias="startDate")]
+ """The start date for trial links.
+
+ Keep empty to get all. Must not be greater than 255 characters.
"""
+
+ synchronous: bool
+ """Wait for revenue calculation instead of processing it in the background."""
diff --git a/src/onlyfansapi/types/user_list_list_params.py b/src/onlyfansapi/types/user_list_list_params.py
index a1213c95..a99daaf5 100644
--- a/src/onlyfansapi/types/user_list_list_params.py
+++ b/src/onlyfansapi/types/user_list_list_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["UserListListParams"]
@@ -17,3 +17,9 @@ class UserListListParams(TypedDict, total=False):
offset: Optional[int]
"""Must be at least 0."""
+
+ view: Literal["queue"]
+ """How to return the results.
+
+ `queue` returns the user lists that are available for Mass-Messaging.
+ """
diff --git a/src/onlyfansapi/types/user_lists/user_add_params.py b/src/onlyfansapi/types/user_lists/user_add_params.py
index c9076b97..b1c49e64 100644
--- a/src/onlyfansapi/types/user_lists/user_add_params.py
+++ b/src/onlyfansapi/types/user_lists/user_add_params.py
@@ -14,3 +14,14 @@ class UserAddParams(TypedDict, total=False):
ids: Required[SequenceNotStr[str]]
"""Array of OnlyFans User IDs to be added into the list"""
+
+ skip_invalid: bool
+ """
+ Set to `true` to skip the User IDs OnlyFans refuses instead of failing the whole
+ batch. We drop the rejected IDs and retry the remainder for you (up to 5
+ OnlyFans attempts, each costing 1 credit), then respond `200` with `data.added`
+ (the IDs that made it in) and `data.failed` (an object mapping each rejected
+ User ID to the reason OnlyFans gave). Note this changes the shape of `data` —
+ see the example responses. Failures that are not about individual users (e.g. an
+ invalid or inaccessible list ID) still return the regular `400`.
+ """
diff --git a/src/onlyfansapi/types/user_lists/user_add_response.py b/src/onlyfansapi/types/user_lists/user_add_response.py
index ce1322a1..eec84d34 100644
--- a/src/onlyfansapi/types/user_lists/user_add_response.py
+++ b/src/onlyfansapi/types/user_lists/user_add_response.py
@@ -1,21 +1,81 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
+from typing import List, Union, Optional
+from typing_extensions import TypeAlias
from pydantic import Field as FieldInfo
from ..._models import BaseModel
-__all__ = ["UserAddResponse", "_Meta", "_Meta_Cache", "_Meta_Credits", "_Meta_RateLimits", "Data"]
+__all__ = [
+ "UserAddResponse",
+ "UnionMember0",
+ "UnionMember0_Meta",
+ "UnionMember0_Meta_Cache",
+ "UnionMember0_Meta_Credits",
+ "UnionMember0_Meta_RateLimits",
+ "UnionMember0Data",
+ "UnionMember1",
+ "UnionMember1_Meta",
+ "UnionMember1_Meta_Cache",
+ "UnionMember1_Meta_Credits",
+ "UnionMember1_Meta_RateLimits",
+ "UnionMember1Data",
+ "UnionMember1DataFailed",
+]
+
+
+class UnionMember0_Meta_Cache(BaseModel):
+ is_cached: Optional[bool] = None
+
+ note: Optional[str] = None
+
+
+class UnionMember0_Meta_Credits(BaseModel):
+ balance: Optional[int] = None
+
+ note: Optional[str] = None
+
+ used: Optional[int] = None
+
+
+class UnionMember0_Meta_RateLimits(BaseModel):
+ limit_day: Optional[int] = None
+
+ limit_minute: Optional[int] = None
+
+ remaining_day: Optional[int] = None
+
+ remaining_minute: Optional[int] = None
-class _Meta_Cache(BaseModel):
+class UnionMember0_Meta(BaseModel):
+ api_cache: Optional[UnionMember0_Meta_Cache] = FieldInfo(alias="_cache", default=None)
+
+ api_credits: Optional[UnionMember0_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+
+ api_rate_limits: Optional[UnionMember0_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
+
+
+class UnionMember0Data(BaseModel):
+ api_1224114714: Optional[List[int]] = FieldInfo(alias="1224114714", default=None)
+
+
+class UnionMember0(BaseModel):
+ """Default: OnlyFans accepted every User ID"""
+
+ api_meta: Optional[UnionMember0_Meta] = FieldInfo(alias="_meta", default=None)
+
+ data: Optional[UnionMember0Data] = None
+
+
+class UnionMember1_Meta_Cache(BaseModel):
is_cached: Optional[bool] = None
note: Optional[str] = None
-class _Meta_Credits(BaseModel):
+class UnionMember1_Meta_Credits(BaseModel):
balance: Optional[int] = None
note: Optional[str] = None
@@ -23,7 +83,7 @@ class _Meta_Credits(BaseModel):
used: Optional[int] = None
-class _Meta_RateLimits(BaseModel):
+class UnionMember1_Meta_RateLimits(BaseModel):
limit_day: Optional[int] = None
limit_minute: Optional[int] = None
@@ -33,19 +93,32 @@ class _Meta_RateLimits(BaseModel):
remaining_minute: Optional[int] = None
-class _Meta(BaseModel):
- api_cache: Optional[_Meta_Cache] = FieldInfo(alias="_cache", default=None)
+class UnionMember1_Meta(BaseModel):
+ api_cache: Optional[UnionMember1_Meta_Cache] = FieldInfo(alias="_cache", default=None)
- api_credits: Optional[_Meta_Credits] = FieldInfo(alias="_credits", default=None)
+ api_credits: Optional[UnionMember1_Meta_Credits] = FieldInfo(alias="_credits", default=None)
- api_rate_limits: Optional[_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
+ api_rate_limits: Optional[UnionMember1_Meta_RateLimits] = FieldInfo(alias="_rate_limits", default=None)
-class Data(BaseModel):
- api_1224114714: Optional[List[int]] = FieldInfo(alias="1224114714", default=None)
+class UnionMember1DataFailed(BaseModel):
+ api_123456: Optional[str] = FieldInfo(alias="123456", default=None)
+
+
+class UnionMember1Data(BaseModel):
+ added: Optional[List[int]] = None
+
+ failed: Optional[UnionMember1DataFailed] = None
+
+
+class UnionMember1(BaseModel):
+ """
+ With `skip_invalid=true`: the rejected User IDs are reported instead of failing the batch
+ """
+
+ api_meta: Optional[UnionMember1_Meta] = FieldInfo(alias="_meta", default=None)
+ data: Optional[UnionMember1Data] = None
-class UserAddResponse(BaseModel):
- api_meta: Optional[_Meta] = FieldInfo(alias="_meta", default=None)
- data: Optional[Data] = None
+UserAddResponse: TypeAlias = Union[UnionMember0, UnionMember1]
diff --git a/src/onlyfansapi/types/webhook_create_params.py b/src/onlyfansapi/types/webhook_create_params.py
index 2db4b039..d99e4b3b 100644
--- a/src/onlyfansapi/types/webhook_create_params.py
+++ b/src/onlyfansapi/types/webhook_create_params.py
@@ -12,7 +12,7 @@
class WebhookCreateParams(TypedDict, total=False):
account_scope: Required[str]
- """The account scope for the webhook.
+ """The account scope for the webhook (OnlyFans and Fansly webhooks alike).
Use "global" for all accounts, "inclusive" for only selected accounts, or
"exclusive" for all except selected accounts.
@@ -24,13 +24,17 @@ class WebhookCreateParams(TypedDict, total=False):
events: Required[SequenceNotStr[str]]
"""An array of webhook events to subscribe to.
- For all options, refer to our **List Available Events** endpoint.
+ For all options, refer to our **List Available Events** endpoint. A webhook is
+ single-platform: subscribe to either OnlyFans events or Fansly (`fansly.*`)
+ events, never both in one webhook.
"""
account_ids: SequenceNotStr[str]
"""An array of account IDs to apply the scope to.
- Required unless account_scope is "global".
+ Use OnlyFans account IDs (`acct_...`) for OnlyFans webhooks and Fansly account
+ IDs (`fansly_acct_...`) for Fansly webhooks. Required unless account_scope is
+ "global".
"""
signing_secret: Optional[str]
diff --git a/src/onlyfansapi/types/webhook_update_params.py b/src/onlyfansapi/types/webhook_update_params.py
index 2a95cdff..62f8dfb7 100644
--- a/src/onlyfansapi/types/webhook_update_params.py
+++ b/src/onlyfansapi/types/webhook_update_params.py
@@ -12,7 +12,7 @@
class WebhookUpdateParams(TypedDict, total=False):
account_scope: Required[str]
- """The account scope for the webhook.
+ """The account scope for the webhook (OnlyFans and Fansly webhooks alike).
Use "global" for all accounts, "inclusive" for only selected accounts, or
"exclusive" for all except selected accounts.
@@ -24,13 +24,17 @@ class WebhookUpdateParams(TypedDict, total=False):
events: Required[SequenceNotStr[str]]
"""An array of webhook events to subscribe to.
- For all options, refer to our **List Available Events** endpoint.
+ For all options, refer to our **List Available Events** endpoint. A webhook is
+ single-platform: subscribe to either OnlyFans events or Fansly (`fansly.*`)
+ events, never both in one webhook.
"""
account_ids: SequenceNotStr[str]
"""An array of account IDs to apply the scope to.
- Required unless account_scope is "global".
+ Use OnlyFans account IDs (`acct_...`) for OnlyFans webhooks and Fansly account
+ IDs (`fansly_acct_...`) for Fansly webhooks. Required unless account_scope is
+ "global".
"""
enabled: Optional[bool]
diff --git a/tests/api_resources/chats/test_messages.py b/tests/api_resources/chats/test_messages.py
index 07c8373f..053affc7 100644
--- a/tests/api_resources/chats/test_messages.py
+++ b/tests/api_resources/chats/test_messages.py
@@ -422,16 +422,18 @@ def test_method_send_with_all_params(self, client: OnlyFansAPI) -> None:
message = client.chats.messages.send(
chat_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ block_banned_words="strict_ban",
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
- price=10,
+ price=6.97,
reply_to_message_id=123456789,
rf_guest="rfGuest",
rf_partner="rfPartner",
rf_tag="rfTag",
text="Hello!",
+ idempotency_key="a1b2c3d4-5e6f-4789-a0b1-c2d3e4f5a6b7",
)
assert_matches_type(MessageSendResponse, message, path=["response"])
@@ -1007,16 +1009,18 @@ async def test_method_send_with_all_params(self, async_client: AsyncOnlyFansAPI)
message = await async_client.chats.messages.send(
chat_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ block_banned_words="strict_ban",
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
- price=10,
+ price=6.97,
reply_to_message_id=123456789,
rf_guest="rfGuest",
rf_partner="rfPartner",
rf_tag="rfTag",
text="Hello!",
+ idempotency_key="a1b2c3d4-5e6f-4789-a0b1-c2d3e4f5a6b7",
)
assert_matches_type(MessageSendResponse, message, path=["response"])
diff --git a/tests/api_resources/engagement/test_messages.py b/tests/api_resources/engagement/test_messages.py
index a4e86aa2..e3986949 100644
--- a/tests/api_resources/engagement/test_messages.py
+++ b/tests/api_resources/engagement/test_messages.py
@@ -24,7 +24,7 @@ class TestMessages:
@parametrize
def test_method_get_message_buyers(self, client: OnlyFansAPI) -> None:
message = client.engagement.messages.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(MessageGetMessageBuyersResponse, message, path=["response"])
@@ -33,7 +33,7 @@ def test_method_get_message_buyers(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_get_message_buyers_with_all_params(self, client: OnlyFansAPI) -> None:
message = client.engagement.messages.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
marker=0,
@@ -47,7 +47,7 @@ def test_method_get_message_buyers_with_all_params(self, client: OnlyFansAPI) ->
@parametrize
def test_raw_response_get_message_buyers(self, client: OnlyFansAPI) -> None:
response = client.engagement.messages.with_raw_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -60,7 +60,7 @@ def test_raw_response_get_message_buyers(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_get_message_buyers(self, client: OnlyFansAPI) -> None:
with client.engagement.messages.with_streaming_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -76,7 +76,7 @@ def test_streaming_response_get_message_buyers(self, client: OnlyFansAPI) -> Non
def test_path_params_get_message_buyers(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.engagement.messages.with_raw_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="",
)
@@ -148,7 +148,7 @@ class TestAsyncMessages:
@parametrize
async def test_method_get_message_buyers(self, async_client: AsyncOnlyFansAPI) -> None:
message = await async_client.engagement.messages.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(MessageGetMessageBuyersResponse, message, path=["response"])
@@ -157,7 +157,7 @@ async def test_method_get_message_buyers(self, async_client: AsyncOnlyFansAPI) -
@parametrize
async def test_method_get_message_buyers_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
message = await async_client.engagement.messages.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
marker=0,
@@ -171,7 +171,7 @@ async def test_method_get_message_buyers_with_all_params(self, async_client: Asy
@parametrize
async def test_raw_response_get_message_buyers(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.engagement.messages.with_raw_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -184,7 +184,7 @@ async def test_raw_response_get_message_buyers(self, async_client: AsyncOnlyFans
@parametrize
async def test_streaming_response_get_message_buyers(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.engagement.messages.with_streaming_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -200,7 +200,7 @@ async def test_streaming_response_get_message_buyers(self, async_client: AsyncOn
async def test_path_params_get_message_buyers(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.engagement.messages.with_raw_response.get_message_buyers(
- message_id="voluptatem",
+ message_id="ipsa",
account="",
)
diff --git a/tests/api_resources/media/vault/lists/test_media.py b/tests/api_resources/media/vault/lists/test_media.py
index de76d677..283ca8bb 100644
--- a/tests/api_resources/media/vault/lists/test_media.py
+++ b/tests/api_resources/media/vault/lists/test_media.py
@@ -24,7 +24,7 @@ class TestMedia:
@parametrize
def test_method_add(self, client: OnlyFansAPI) -> None:
media = client.media.vault.lists.media.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -34,7 +34,7 @@ def test_method_add(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_add(self, client: OnlyFansAPI) -> None:
response = client.media.vault.lists.media.with_raw_response.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -48,7 +48,7 @@ def test_raw_response_add(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_add(self, client: OnlyFansAPI) -> None:
with client.media.vault.lists.media.with_streaming_response.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
) as response:
@@ -65,7 +65,7 @@ def test_streaming_response_add(self, client: OnlyFansAPI) -> None:
def test_path_params_add(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.media.vault.lists.media.with_raw_response.add(
- list_id="hic",
+ list_id="qui",
account="",
media_ids=["string"],
)
@@ -81,7 +81,7 @@ def test_path_params_add(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_remove(self, client: OnlyFansAPI) -> None:
media = client.media.vault.lists.media.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -91,7 +91,7 @@ def test_method_remove(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_remove(self, client: OnlyFansAPI) -> None:
response = client.media.vault.lists.media.with_raw_response.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -105,7 +105,7 @@ def test_raw_response_remove(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_remove(self, client: OnlyFansAPI) -> None:
with client.media.vault.lists.media.with_streaming_response.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
) as response:
@@ -122,7 +122,7 @@ def test_streaming_response_remove(self, client: OnlyFansAPI) -> None:
def test_path_params_remove(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.media.vault.lists.media.with_raw_response.remove(
- list_id="hic",
+ list_id="qui",
account="",
media_ids=["string"],
)
@@ -144,7 +144,7 @@ class TestAsyncMedia:
@parametrize
async def test_method_add(self, async_client: AsyncOnlyFansAPI) -> None:
media = await async_client.media.vault.lists.media.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -154,7 +154,7 @@ async def test_method_add(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_add(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.media.vault.lists.media.with_raw_response.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -168,7 +168,7 @@ async def test_raw_response_add(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_streaming_response_add(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.media.vault.lists.media.with_streaming_response.add(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
) as response:
@@ -185,7 +185,7 @@ async def test_streaming_response_add(self, async_client: AsyncOnlyFansAPI) -> N
async def test_path_params_add(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.media.vault.lists.media.with_raw_response.add(
- list_id="hic",
+ list_id="qui",
account="",
media_ids=["string"],
)
@@ -201,7 +201,7 @@ async def test_path_params_add(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_remove(self, async_client: AsyncOnlyFansAPI) -> None:
media = await async_client.media.vault.lists.media.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -211,7 +211,7 @@ async def test_method_remove(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_remove(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.media.vault.lists.media.with_raw_response.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
)
@@ -225,7 +225,7 @@ async def test_raw_response_remove(self, async_client: AsyncOnlyFansAPI) -> None
@parametrize
async def test_streaming_response_remove(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.media.vault.lists.media.with_streaming_response.remove(
- list_id="hic",
+ list_id="qui",
account="acct_XXXXXXXXXXXXXXX",
media_ids=["string"],
) as response:
@@ -242,7 +242,7 @@ async def test_streaming_response_remove(self, async_client: AsyncOnlyFansAPI) -
async def test_path_params_remove(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.media.vault.lists.media.with_raw_response.remove(
- list_id="hic",
+ list_id="qui",
account="",
media_ids=["string"],
)
diff --git a/tests/api_resources/media/vault/test_lists.py b/tests/api_resources/media/vault/test_lists.py
index 2602218c..008cfa79 100644
--- a/tests/api_resources/media/vault/test_lists.py
+++ b/tests/api_resources/media/vault/test_lists.py
@@ -127,6 +127,7 @@ def test_method_update(self, client: OnlyFansAPI) -> None:
list_ = client.media.vault.lists.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
assert_matches_type(ListUpdateResponse, list_, path=["response"])
@@ -136,6 +137,7 @@ def test_raw_response_update(self, client: OnlyFansAPI) -> None:
response = client.media.vault.lists.with_raw_response.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
assert response.is_closed is True
@@ -149,6 +151,7 @@ def test_streaming_response_update(self, client: OnlyFansAPI) -> None:
with client.media.vault.lists.with_streaming_response.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -165,12 +168,14 @@ def test_path_params_update(self, client: OnlyFansAPI) -> None:
client.media.vault.lists.with_raw_response.update(
list_id="123",
account="",
+ name="My renamed list",
)
with pytest.raises(ValueError, match=r"Expected a non-empty value for `list_id` but received ''"):
client.media.vault.lists.with_raw_response.update(
list_id="",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -186,6 +191,7 @@ def test_method_list(self, client: OnlyFansAPI) -> None:
def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
list_ = client.media.vault.lists.list(
account="acct_XXXXXXXXXXXXXXX",
+ lightweight=True,
limit=24,
offset=0,
query="My list name",
@@ -388,6 +394,7 @@ async def test_method_update(self, async_client: AsyncOnlyFansAPI) -> None:
list_ = await async_client.media.vault.lists.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
assert_matches_type(ListUpdateResponse, list_, path=["response"])
@@ -397,6 +404,7 @@ async def test_raw_response_update(self, async_client: AsyncOnlyFansAPI) -> None
response = await async_client.media.vault.lists.with_raw_response.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
assert response.is_closed is True
@@ -410,6 +418,7 @@ async def test_streaming_response_update(self, async_client: AsyncOnlyFansAPI) -
async with async_client.media.vault.lists.with_streaming_response.update(
list_id="123",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -426,12 +435,14 @@ async def test_path_params_update(self, async_client: AsyncOnlyFansAPI) -> None:
await async_client.media.vault.lists.with_raw_response.update(
list_id="123",
account="",
+ name="My renamed list",
)
with pytest.raises(ValueError, match=r"Expected a non-empty value for `list_id` but received ''"):
await async_client.media.vault.lists.with_raw_response.update(
list_id="",
account="acct_XXXXXXXXXXXXXXX",
+ name="My renamed list",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -447,6 +458,7 @@ async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
list_ = await async_client.media.vault.lists.list(
account="acct_XXXXXXXXXXXXXXX",
+ lightweight=True,
limit=24,
offset=0,
query="My list name",
diff --git a/tests/api_resources/posts/test_comments.py b/tests/api_resources/posts/test_comments.py
index 297ac0a2..d809aa5d 100644
--- a/tests/api_resources/posts/test_comments.py
+++ b/tests/api_resources/posts/test_comments.py
@@ -29,7 +29,7 @@ class TestComments:
@parametrize
def test_method_create(self, client: OnlyFansAPI) -> None:
comment = client.posts.comments.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
)
@@ -39,7 +39,7 @@ def test_method_create(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_create_with_all_params(self, client: OnlyFansAPI) -> None:
comment = client.posts.comments.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
answer_to=123,
@@ -51,7 +51,7 @@ def test_method_create_with_all_params(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_create(self, client: OnlyFansAPI) -> None:
response = client.posts.comments.with_raw_response.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
)
@@ -65,7 +65,7 @@ def test_raw_response_create(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_create(self, client: OnlyFansAPI) -> None:
with client.posts.comments.with_streaming_response.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
) as response:
@@ -82,7 +82,7 @@ def test_streaming_response_create(self, client: OnlyFansAPI) -> None:
def test_path_params_create(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.posts.comments.with_raw_response.create(
- post_id="dicta",
+ post_id="quis",
account="",
text="This is a comment.",
)
@@ -98,7 +98,7 @@ def test_path_params_create(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list(self, client: OnlyFansAPI) -> None:
comment = client.posts.comments.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(CommentListResponse, comment, path=["response"])
@@ -107,7 +107,7 @@ def test_method_list(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
comment = client.posts.comments.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -119,7 +119,7 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_list(self, client: OnlyFansAPI) -> None:
response = client.posts.comments.with_raw_response.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -132,7 +132,7 @@ def test_raw_response_list(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list(self, client: OnlyFansAPI) -> None:
with client.posts.comments.with_streaming_response.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -148,7 +148,7 @@ def test_streaming_response_list(self, client: OnlyFansAPI) -> None:
def test_path_params_list(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.posts.comments.with_raw_response.list(
- post_id="dicta",
+ post_id="quis",
account="",
)
@@ -418,7 +418,7 @@ class TestAsyncComments:
@parametrize
async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
comment = await async_client.posts.comments.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
)
@@ -428,7 +428,7 @@ async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
comment = await async_client.posts.comments.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
answer_to=123,
@@ -440,7 +440,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOnlyFansAP
@parametrize
async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.posts.comments.with_raw_response.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
)
@@ -454,7 +454,7 @@ async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None
@parametrize
async def test_streaming_response_create(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.posts.comments.with_streaming_response.create(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
text="This is a comment.",
) as response:
@@ -471,7 +471,7 @@ async def test_streaming_response_create(self, async_client: AsyncOnlyFansAPI) -
async def test_path_params_create(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.posts.comments.with_raw_response.create(
- post_id="dicta",
+ post_id="quis",
account="",
text="This is a comment.",
)
@@ -487,7 +487,7 @@ async def test_path_params_create(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
comment = await async_client.posts.comments.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(CommentListResponse, comment, path=["response"])
@@ -496,7 +496,7 @@ async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
comment = await async_client.posts.comments.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -508,7 +508,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.posts.comments.with_raw_response.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -521,7 +521,7 @@ async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_streaming_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.posts.comments.with_streaming_response.list(
- post_id="dicta",
+ post_id="quis",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -537,7 +537,7 @@ async def test_streaming_response_list(self, async_client: AsyncOnlyFansAPI) ->
async def test_path_params_list(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.posts.comments.with_raw_response.list(
- post_id="dicta",
+ post_id="quis",
account="",
)
diff --git a/tests/api_resources/saved_for_later/posts/test_settings.py b/tests/api_resources/saved_for_later/posts/test_settings.py
index b5f3d61a..fc7b1635 100644
--- a/tests/api_resources/saved_for_later/posts/test_settings.py
+++ b/tests/api_resources/saved_for_later/posts/test_settings.py
@@ -110,7 +110,7 @@ def test_path_params_disable_automatic_posting(self, client: OnlyFansAPI) -> Non
def test_method_enable_or_update_automatic_posting(self, client: OnlyFansAPI) -> None:
setting = client.saved_for_later.posts.settings.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
)
assert_matches_type(SettingEnableOrUpdateAutomaticPostingResponse, setting, path=["response"])
@@ -119,7 +119,7 @@ def test_method_enable_or_update_automatic_posting(self, client: OnlyFansAPI) ->
def test_raw_response_enable_or_update_automatic_posting(self, client: OnlyFansAPI) -> None:
response = client.saved_for_later.posts.settings.with_raw_response.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
)
assert response.is_closed is True
@@ -132,7 +132,7 @@ def test_raw_response_enable_or_update_automatic_posting(self, client: OnlyFansA
def test_streaming_response_enable_or_update_automatic_posting(self, client: OnlyFansAPI) -> None:
with client.saved_for_later.posts.settings.with_streaming_response.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -148,7 +148,7 @@ def test_path_params_enable_or_update_automatic_posting(self, client: OnlyFansAP
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.saved_for_later.posts.settings.with_raw_response.enable_or_update_automatic_posting(
account="",
- period=24,
+ period=6,
)
@@ -246,7 +246,7 @@ async def test_path_params_disable_automatic_posting(self, async_client: AsyncOn
async def test_method_enable_or_update_automatic_posting(self, async_client: AsyncOnlyFansAPI) -> None:
setting = await async_client.saved_for_later.posts.settings.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
)
assert_matches_type(SettingEnableOrUpdateAutomaticPostingResponse, setting, path=["response"])
@@ -256,7 +256,7 @@ async def test_raw_response_enable_or_update_automatic_posting(self, async_clien
response = (
await async_client.saved_for_later.posts.settings.with_raw_response.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
)
)
@@ -271,7 +271,7 @@ async def test_streaming_response_enable_or_update_automatic_posting(self, async
async with (
async_client.saved_for_later.posts.settings.with_streaming_response.enable_or_update_automatic_posting(
account="acct_XXXXXXXXXXXXXXX",
- period=24,
+ period=6,
)
) as response:
assert not response.is_closed
@@ -288,5 +288,5 @@ async def test_path_params_enable_or_update_automatic_posting(self, async_client
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.saved_for_later.posts.settings.with_raw_response.enable_or_update_automatic_posting(
account="",
- period=24,
+ period=6,
)
diff --git a/tests/api_resources/settings/test_welcome_message.py b/tests/api_resources/settings/test_welcome_message.py
index 544df889..9664075f 100644
--- a/tests/api_resources/settings/test_welcome_message.py
+++ b/tests/api_resources/settings/test_welcome_message.py
@@ -76,7 +76,7 @@ def test_method_update(self, client: OnlyFansAPI) -> None:
def test_method_update_with_all_params(self, client: OnlyFansAPI) -> None:
welcome_message = client.settings.welcome_message.update(
account="acct_XXXXXXXXXXXXXXX",
- is_forward=True,
+ is_forward=False,
locked_text=False,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
@@ -229,7 +229,7 @@ async def test_method_update(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
welcome_message = await async_client.settings.welcome_message.update(
account="acct_XXXXXXXXXXXXXXX",
- is_forward=True,
+ is_forward=False,
locked_text=False,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
diff --git a/tests/api_resources/statistics/test_statements.py b/tests/api_resources/statistics/test_statements.py
index 760cbd0e..5630a4ac 100644
--- a/tests/api_resources/statistics/test_statements.py
+++ b/tests/api_resources/statistics/test_statements.py
@@ -22,6 +22,7 @@ class TestStatements:
def test_method_get_earnings(self, client: OnlyFansAPI) -> None:
statement = client.statistics.statements.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
assert_matches_type(StatementGetEarningsResponse, statement, path=["response"])
@@ -31,8 +32,8 @@ def test_method_get_earnings(self, client: OnlyFansAPI) -> None:
def test_method_get_earnings_with_all_params(self, client: OnlyFansAPI) -> None:
statement = client.statistics.statements.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
- start_date="2025-01-01 00:00:00",
end_date="2025-03-31 23:59:59",
+ start_date="2025-01-01 00:00:00",
type="total",
)
assert_matches_type(StatementGetEarningsResponse, statement, path=["response"])
@@ -42,6 +43,7 @@ def test_method_get_earnings_with_all_params(self, client: OnlyFansAPI) -> None:
def test_raw_response_get_earnings(self, client: OnlyFansAPI) -> None:
response = client.statistics.statements.with_raw_response.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
@@ -55,6 +57,7 @@ def test_raw_response_get_earnings(self, client: OnlyFansAPI) -> None:
def test_streaming_response_get_earnings(self, client: OnlyFansAPI) -> None:
with client.statistics.statements.with_streaming_response.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
) as response:
assert not response.is_closed
@@ -71,6 +74,7 @@ def test_path_params_get_earnings(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.statistics.statements.with_raw_response.get_earnings(
account="",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
@@ -85,6 +89,7 @@ class TestAsyncStatements:
async def test_method_get_earnings(self, async_client: AsyncOnlyFansAPI) -> None:
statement = await async_client.statistics.statements.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
assert_matches_type(StatementGetEarningsResponse, statement, path=["response"])
@@ -94,8 +99,8 @@ async def test_method_get_earnings(self, async_client: AsyncOnlyFansAPI) -> None
async def test_method_get_earnings_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
statement = await async_client.statistics.statements.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
- start_date="2025-01-01 00:00:00",
end_date="2025-03-31 23:59:59",
+ start_date="2025-01-01 00:00:00",
type="total",
)
assert_matches_type(StatementGetEarningsResponse, statement, path=["response"])
@@ -105,6 +110,7 @@ async def test_method_get_earnings_with_all_params(self, async_client: AsyncOnly
async def test_raw_response_get_earnings(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.statistics.statements.with_raw_response.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
@@ -118,6 +124,7 @@ async def test_raw_response_get_earnings(self, async_client: AsyncOnlyFansAPI) -
async def test_streaming_response_get_earnings(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.statistics.statements.with_streaming_response.get_earnings(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
) as response:
assert not response.is_closed
@@ -134,5 +141,6 @@ async def test_path_params_get_earnings(self, async_client: AsyncOnlyFansAPI) ->
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.statistics.statements.with_raw_response.get_earnings(
account="",
+ end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
)
diff --git a/tests/api_resources/stories/test_highlights.py b/tests/api_resources/stories/test_highlights.py
index 06d474b9..9637e284 100644
--- a/tests/api_resources/stories/test_highlights.py
+++ b/tests/api_resources/stories/test_highlights.py
@@ -285,7 +285,7 @@ def test_path_params_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_add_story(self, client: OnlyFansAPI) -> None:
highlight = client.stories.highlights.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -296,7 +296,7 @@ def test_method_add_story(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_add_story(self, client: OnlyFansAPI) -> None:
response = client.stories.highlights.with_raw_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -311,7 +311,7 @@ def test_raw_response_add_story(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_add_story(self, client: OnlyFansAPI) -> None:
with client.stories.highlights.with_streaming_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -329,7 +329,7 @@ def test_streaming_response_add_story(self, client: OnlyFansAPI) -> None:
def test_path_params_add_story(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.stories.highlights.with_raw_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -347,7 +347,7 @@ def test_path_params_add_story(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_remove_story(self, client: OnlyFansAPI) -> None:
highlight = client.stories.highlights.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
)
@@ -357,7 +357,7 @@ def test_method_remove_story(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_remove_story(self, client: OnlyFansAPI) -> None:
response = client.stories.highlights.with_raw_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
)
@@ -371,7 +371,7 @@ def test_raw_response_remove_story(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_remove_story(self, client: OnlyFansAPI) -> None:
with client.stories.highlights.with_streaming_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
) as response:
@@ -388,7 +388,7 @@ def test_streaming_response_remove_story(self, client: OnlyFansAPI) -> None:
def test_path_params_remove_story(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.stories.highlights.with_raw_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="",
highlight_id=1234567890,
)
@@ -666,7 +666,7 @@ async def test_path_params_delete(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_add_story(self, async_client: AsyncOnlyFansAPI) -> None:
highlight = await async_client.stories.highlights.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -677,7 +677,7 @@ async def test_method_add_story(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_add_story(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.stories.highlights.with_raw_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -692,7 +692,7 @@ async def test_raw_response_add_story(self, async_client: AsyncOnlyFansAPI) -> N
@parametrize
async def test_streaming_response_add_story(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.stories.highlights.with_streaming_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -710,7 +710,7 @@ async def test_streaming_response_add_story(self, async_client: AsyncOnlyFansAPI
async def test_path_params_add_story(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.stories.highlights.with_raw_response.add_story(
- path_story_id="autem",
+ path_story_id="saepe",
account="",
highlight_id=1234567890,
body_story_id=2345678901,
@@ -728,7 +728,7 @@ async def test_path_params_add_story(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_method_remove_story(self, async_client: AsyncOnlyFansAPI) -> None:
highlight = await async_client.stories.highlights.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
)
@@ -738,7 +738,7 @@ async def test_method_remove_story(self, async_client: AsyncOnlyFansAPI) -> None
@parametrize
async def test_raw_response_remove_story(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.stories.highlights.with_raw_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
)
@@ -752,7 +752,7 @@ async def test_raw_response_remove_story(self, async_client: AsyncOnlyFansAPI) -
@parametrize
async def test_streaming_response_remove_story(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.stories.highlights.with_streaming_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="acct_XXXXXXXXXXXXXXX",
highlight_id=1234567890,
) as response:
@@ -769,7 +769,7 @@ async def test_streaming_response_remove_story(self, async_client: AsyncOnlyFans
async def test_path_params_remove_story(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.stories.highlights.with_raw_response.remove_story(
- story_id="autem",
+ story_id="saepe",
account="",
highlight_id=1234567890,
)
diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/test_accounts.py
index 02cf31a0..28f9196e 100644
--- a/tests/api_resources/test_accounts.py
+++ b/tests/api_resources/test_accounts.py
@@ -59,7 +59,7 @@ def test_streaming_response_list(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_disconnect(self, client: OnlyFansAPI) -> None:
account = client.accounts.disconnect(
- "sed",
+ "in",
)
assert_matches_type(Optional[AccountDisconnectResponse], account, path=["response"])
@@ -67,7 +67,7 @@ def test_method_disconnect(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_disconnect(self, client: OnlyFansAPI) -> None:
response = client.accounts.with_raw_response.disconnect(
- "sed",
+ "in",
)
assert response.is_closed is True
@@ -79,7 +79,7 @@ def test_raw_response_disconnect(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_disconnect(self, client: OnlyFansAPI) -> None:
with client.accounts.with_streaming_response.disconnect(
- "sed",
+ "in",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -145,7 +145,7 @@ async def test_streaming_response_list(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_method_disconnect(self, async_client: AsyncOnlyFansAPI) -> None:
account = await async_client.accounts.disconnect(
- "sed",
+ "in",
)
assert_matches_type(Optional[AccountDisconnectResponse], account, path=["response"])
@@ -153,7 +153,7 @@ async def test_method_disconnect(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_disconnect(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.accounts.with_raw_response.disconnect(
- "sed",
+ "in",
)
assert response.is_closed is True
@@ -165,7 +165,7 @@ async def test_raw_response_disconnect(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_streaming_response_disconnect(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.accounts.with_streaming_response.disconnect(
- "sed",
+ "in",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_authenticate.py b/tests/api_resources/test_authenticate.py
index 6d4a3d4e..c4ddf679 100644
--- a/tests/api_resources/test_authenticate.py
+++ b/tests/api_resources/test_authenticate.py
@@ -159,22 +159,22 @@ def test_method_start(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_start_with_all_params(self, client: OnlyFansAPI) -> None:
authenticate = client.authenticate.start(
- auth_id="aut",
- auth_type="raw_data",
- cookies="nihil",
+ auth_id="saepe",
+ auth_type="email_password",
+ cookies="quo",
custom_proxy={
"host": "proxy.example.com",
- "password": "]%<>fOacrc# None:
@parametrize
async def test_method_start_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
authenticate = await async_client.authenticate.start(
- auth_id="aut",
- auth_type="raw_data",
- cookies="nihil",
+ auth_id="saepe",
+ auth_type="email_password",
+ cookies="quo",
custom_proxy={
"host": "proxy.example.com",
- "password": "]%<>fOacrc# None:
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
@@ -152,6 +153,7 @@ def test_method_list_all_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
@@ -212,6 +214,7 @@ def test_method_list_expired_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
@@ -495,6 +498,7 @@ async def test_method_list_active_with_all_params(self, async_client: AsyncOnlyF
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
@@ -555,6 +559,7 @@ async def test_method_list_all_with_all_params(self, async_client: AsyncOnlyFans
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
@@ -615,6 +620,7 @@ async def test_method_list_expired_with_all_params(self, async_client: AsyncOnly
account="acct_XXXXXXXXXXXXXXX",
filter={
"duration": 0,
+ "max_total_spent": 0,
"online": None,
"tips": 0,
"total_spent": 0,
diff --git a/tests/api_resources/test_following.py b/tests/api_resources/test_following.py
index 3fa2f038..e650457e 100644
--- a/tests/api_resources/test_following.py
+++ b/tests/api_resources/test_following.py
@@ -41,6 +41,8 @@ def test_method_list_active_with_all_params(self, client: OnlyFansAPI) -> None:
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListActiveResponse, following, path=["response"])
@@ -98,6 +100,8 @@ def test_method_list_all_with_all_params(self, client: OnlyFansAPI) -> None:
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListAllResponse, following, path=["response"])
@@ -155,6 +159,8 @@ def test_method_list_expired_with_all_params(self, client: OnlyFansAPI) -> None:
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListExpiredResponse, following, path=["response"])
@@ -218,6 +224,8 @@ async def test_method_list_active_with_all_params(self, async_client: AsyncOnlyF
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListActiveResponse, following, path=["response"])
@@ -275,6 +283,8 @@ async def test_method_list_all_with_all_params(self, async_client: AsyncOnlyFans
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListAllResponse, following, path=["response"])
@@ -332,6 +342,8 @@ async def test_method_list_expired_with_all_params(self, async_client: AsyncOnly
limit=10,
offset=0,
query="john",
+ sort="subscribe_date",
+ sort_direction="desc",
)
assert_matches_type(FollowingListExpiredResponse, following, path=["response"])
diff --git a/tests/api_resources/test_mass_messaging.py b/tests/api_resources/test_mass_messaging.py
index ca7be956..f73a0bc0 100644
--- a/tests/api_resources/test_mass_messaging.py
+++ b/tests/api_resources/test_mass_messaging.py
@@ -93,11 +93,12 @@ def test_method_update_with_all_params(self, client: OnlyFansAPI) -> None:
id="id",
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", "string"],
previews=["ofapi_media_abc123", "string"],
- price=100,
+ price=6.97,
scheduled_date="2025-01-01T00:00:00.000Z",
user_ids=["string"],
user_lists=["fans", "recent", "following", "rebill_off", "tagged", "string"],
@@ -314,12 +315,13 @@ def test_method_send_with_all_params(self, client: OnlyFansAPI) -> None:
mass_messaging = client.mass_messaging.send(
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
excluded_lists=["fans", "recent", "following", "rebill_off", "tagged", "string"],
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
- price=100,
+ price=6.97,
rf_guest="rfGuest",
rf_partner="rfPartner",
rf_tag="rfTag",
@@ -442,11 +444,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncOnlyFansAP
id="id",
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", "string"],
previews=["ofapi_media_abc123", "string"],
- price=100,
+ price=6.97,
scheduled_date="2025-01-01T00:00:00.000Z",
user_ids=["string"],
user_lists=["fans", "recent", "following", "rebill_off", "tagged", "string"],
@@ -663,12 +666,13 @@ async def test_method_send_with_all_params(self, async_client: AsyncOnlyFansAPI)
mass_messaging = await async_client.mass_messaging.send(
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
excluded_lists=["fans", "recent", "following", "rebill_off", "tagged", "string"],
giphy_id="WAGC3LeqJvXglm5H7a",
locked_text=True,
media_files=["ofapi_media_abc123", 1234567890],
previews=["ofapi_media_abc123", 1234567890],
- price=100,
+ price=6.97,
rf_guest="rfGuest",
rf_partner="rfPartner",
rf_tag="rfTag",
diff --git a/tests/api_resources/test_media.py b/tests/api_resources/test_media.py
index 3bba8196..75dab9ad 100644
--- a/tests/api_resources/test_media.py
+++ b/tests/api_resources/test_media.py
@@ -9,10 +9,7 @@
from onlyfansapi import OnlyFansAPI, AsyncOnlyFansAPI
from tests.utils import assert_matches_type
-from onlyfansapi.types import (
- MediaScrapeResponse,
- MediaUploadResponse,
-)
+from onlyfansapi.types import MediaScrapeResponse, MediaUploadResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -27,7 +24,7 @@ def test_method_download(self, client: OnlyFansAPI) -> None:
cdn_url="cdnUrl",
account="acct_XXXXXXXXXXXXXXX",
)
- assert_matches_type(str, media, path=["response"])
+ assert media is None
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -40,7 +37,7 @@ def test_raw_response_download(self, client: OnlyFansAPI) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
media = response.parse()
- assert_matches_type(str, media, path=["response"])
+ assert media is None
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -53,7 +50,7 @@ def test_streaming_response_download(self, client: OnlyFansAPI) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
media = response.parse()
- assert_matches_type(str, media, path=["response"])
+ assert media is None
assert cast(Any, response.is_closed) is True
@@ -194,7 +191,7 @@ async def test_method_download(self, async_client: AsyncOnlyFansAPI) -> None:
cdn_url="cdnUrl",
account="acct_XXXXXXXXXXXXXXX",
)
- assert_matches_type(str, media, path=["response"])
+ assert media is None
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -207,7 +204,7 @@ async def test_raw_response_download(self, async_client: AsyncOnlyFansAPI) -> No
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
media = await response.parse()
- assert_matches_type(str, media, path=["response"])
+ assert media is None
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -220,7 +217,7 @@ async def test_streaming_response_download(self, async_client: AsyncOnlyFansAPI)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
media = await response.parse()
- assert_matches_type(str, media, path=["response"])
+ assert media is None
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_messages.py b/tests/api_resources/test_messages.py
deleted file mode 100644
index 206c5ef3..00000000
--- a/tests/api_resources/test_messages.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from onlyfansapi import OnlyFansAPI, AsyncOnlyFansAPI
-from tests.utils import assert_matches_type
-from onlyfansapi.types import MessageAttachTagsResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestMessages:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_attach_tags(self, client: OnlyFansAPI) -> None:
- message = client.messages.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- )
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_attach_tags_with_all_params(self, client: OnlyFansAPI) -> None:
- message = client.messages.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- rf_guest="rfGuest",
- rf_partner="rfPartner",
- rf_tag="rfTag",
- )
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_attach_tags(self, client: OnlyFansAPI) -> None:
- response = client.messages.with_raw_response.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = response.parse()
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_attach_tags(self, client: OnlyFansAPI) -> None:
- with client.messages.with_streaming_response.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = response.parse()
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_attach_tags(self, client: OnlyFansAPI) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
- client.messages.with_raw_response.attach_tags(
- message_id="123456789",
- account="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"):
- client.messages.with_raw_response.attach_tags(
- message_id="",
- account="acct_XXXXXXXXXXXXXXX",
- )
-
-
-class TestAsyncMessages:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_attach_tags(self, async_client: AsyncOnlyFansAPI) -> None:
- message = await async_client.messages.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- )
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_attach_tags_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
- message = await async_client.messages.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- rf_guest="rfGuest",
- rf_partner="rfPartner",
- rf_tag="rfTag",
- )
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_attach_tags(self, async_client: AsyncOnlyFansAPI) -> None:
- response = await async_client.messages.with_raw_response.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = await response.parse()
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_attach_tags(self, async_client: AsyncOnlyFansAPI) -> None:
- async with async_client.messages.with_streaming_response.attach_tags(
- message_id="123456789",
- account="acct_XXXXXXXXXXXXXXX",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = await response.parse()
- assert_matches_type(MessageAttachTagsResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_attach_tags(self, async_client: AsyncOnlyFansAPI) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
- await async_client.messages.with_raw_response.attach_tags(
- message_id="123456789",
- account="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"):
- await async_client.messages.with_raw_response.attach_tags(
- message_id="",
- account="acct_XXXXXXXXXXXXXXX",
- )
diff --git a/tests/api_resources/test_notifications.py b/tests/api_resources/test_notifications.py
index 280e3de9..413a2df6 100644
--- a/tests/api_resources/test_notifications.py
+++ b/tests/api_resources/test_notifications.py
@@ -38,7 +38,7 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
from_id=123,
limit=10,
skip_users="all",
- type="comments",
+ type="likes",
)
assert_matches_type(NotificationListResponse, notification, path=["response"])
@@ -228,7 +228,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
from_id=123,
limit=10,
skip_users="all",
- type="comments",
+ type="likes",
)
assert_matches_type(NotificationListResponse, notification, path=["response"])
diff --git a/tests/api_resources/test_payouts.py b/tests/api_resources/test_payouts.py
index b365fa0e..6c388e27 100644
--- a/tests/api_resources/test_payouts.py
+++ b/tests/api_resources/test_payouts.py
@@ -177,8 +177,8 @@ def test_method_retrieve_earning_statistics(self, client: OnlyFansAPI) -> None:
def test_method_retrieve_earning_statistics_with_all_params(self, client: OnlyFansAPI) -> None:
payout = client.payouts.retrieve_earning_statistics(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-01-01 00:00:00, +30days",
- start_date="2025-01-01 00:00:00, -30days",
+ end_date="2025-01-31 23:59:59",
+ start_date="2025-01-01 00:00:00",
)
assert_matches_type(PayoutRetrieveEarningStatisticsResponse, payout, path=["response"])
@@ -463,8 +463,8 @@ async def test_method_retrieve_earning_statistics(self, async_client: AsyncOnlyF
async def test_method_retrieve_earning_statistics_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
payout = await async_client.payouts.retrieve_earning_statistics(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-01-01 00:00:00, +30days",
- start_date="2025-01-01 00:00:00, -30days",
+ end_date="2025-01-31 23:59:59",
+ start_date="2025-01-01 00:00:00",
)
assert_matches_type(PayoutRetrieveEarningStatisticsResponse, payout, path=["response"])
diff --git a/tests/api_resources/test_posts.py b/tests/api_resources/test_posts.py
index cfa5a890..3b6873b1 100644
--- a/tests/api_resources/test_posts.py
+++ b/tests/api_resources/test_posts.py
@@ -41,6 +41,7 @@ def test_method_create_with_all_params(self, client: OnlyFansAPI) -> None:
post = client.posts.create(
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
expire_days=3,
fund_raising_target_amount=30,
fund_raising_tips_presets=["string", "string", "string"],
@@ -157,6 +158,7 @@ def test_method_update_with_all_params(self, client: OnlyFansAPI) -> None:
post_id=1234567890,
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
expire_days=3,
fund_raising_target_amount=30,
fund_raising_tips_presets=["string", "string", "string"],
@@ -552,6 +554,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOnlyFansAP
post = await async_client.posts.create(
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
expire_days=3,
fund_raising_target_amount=30,
fund_raising_tips_presets=["string", "string", "string"],
@@ -668,6 +671,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOnlyFansAP
post_id=1234567890,
account="acct_XXXXXXXXXXXXXXX",
text="Hello!",
+ block_banned_words="strict_ban",
expire_days=3,
fund_raising_target_amount=30,
fund_raising_tips_presets=["string", "string", "string"],
diff --git a/tests/api_resources/test_profiles.py b/tests/api_resources/test_profiles.py
index bd4f6161..65694e23 100644
--- a/tests/api_resources/test_profiles.py
+++ b/tests/api_resources/test_profiles.py
@@ -30,7 +30,7 @@ def test_method_retrieve(self, client: OnlyFansAPI) -> None:
def test_method_retrieve_with_all_params(self, client: OnlyFansAPI) -> None:
profile = client.profiles.retrieve(
username="madison420ivy",
- fresh=False,
+ fresh=True,
)
assert_matches_type(ProfileRetrieveResponse, profile, path=["response"])
@@ -87,7 +87,7 @@ async def test_method_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_retrieve_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
profile = await async_client.profiles.retrieve(
username="madison420ivy",
- fresh=False,
+ fresh=True,
)
assert_matches_type(ProfileRetrieveResponse, profile, path=["response"])
diff --git a/tests/api_resources/test_queue.py b/tests/api_resources/test_queue.py
index b5cda3e9..ed4d6f6f 100644
--- a/tests/api_resources/test_queue.py
+++ b/tests/api_resources/test_queue.py
@@ -26,19 +26,30 @@ class TestQueue:
def test_method_list(self, client: OnlyFansAPI) -> None:
queue = client.queue.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
)
assert_matches_type(QueueListResponse, queue, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
+ queue = client.queue.list(
+ account="acct_XXXXXXXXXXXXXXX",
+ publish_date_end="2025-01-01",
+ publish_date_start="2025-01-01",
+ timezone="Europe/Prague",
+ limit=20,
+ type=["post"],
+ )
+ assert_matches_type(QueueListResponse, queue, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_list(self, client: OnlyFansAPI) -> None:
response = client.queue.with_raw_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
@@ -54,7 +65,6 @@ def test_raw_response_list(self, client: OnlyFansAPI) -> None:
def test_streaming_response_list(self, client: OnlyFansAPI) -> None:
with client.queue.with_streaming_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
@@ -73,7 +83,6 @@ def test_path_params_list(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.queue.with_raw_response.list(
account="",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
@@ -196,19 +205,30 @@ class TestAsyncQueue:
async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
queue = await async_client.queue.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
)
assert_matches_type(QueueListResponse, queue, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
+ queue = await async_client.queue.list(
+ account="acct_XXXXXXXXXXXXXXX",
+ publish_date_end="2025-01-01",
+ publish_date_start="2025-01-01",
+ timezone="Europe/Prague",
+ limit=20,
+ type=["post"],
+ )
+ assert_matches_type(QueueListResponse, queue, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.queue.with_raw_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
@@ -224,7 +244,6 @@ async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_streaming_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.queue.with_streaming_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
@@ -243,7 +262,6 @@ async def test_path_params_list(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.queue.with_raw_response.list(
account="",
- limit=20,
publish_date_end="2025-01-01",
publish_date_start="2025-01-01",
timezone="Europe/Prague",
diff --git a/tests/api_resources/test_shared_tracking_links.py b/tests/api_resources/test_shared_tracking_links.py
index 3dc77196..df210ec6 100644
--- a/tests/api_resources/test_shared_tracking_links.py
+++ b/tests/api_resources/test_shared_tracking_links.py
@@ -35,7 +35,11 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ pagination=1,
+ sorting_deleted=1,
+ stats="true",
synchronous=False,
+ with_deleted=1,
)
assert_matches_type(SharedTrackingLinkListResponse, shared_tracking_link, path=["response"])
@@ -140,7 +144,11 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ pagination=1,
+ sorting_deleted=1,
+ stats="true",
synchronous=False,
+ with_deleted=1,
)
assert_matches_type(SharedTrackingLinkListResponse, shared_tracking_link, path=["response"])
diff --git a/tests/api_resources/test_shared_trial_links.py b/tests/api_resources/test_shared_trial_links.py
index 362e703b..3b03cb92 100644
--- a/tests/api_resources/test_shared_trial_links.py
+++ b/tests/api_resources/test_shared_trial_links.py
@@ -35,6 +35,7 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ pagination=0,
synchronous=False,
)
assert_matches_type(SharedTrialLinkListResponse, shared_trial_link, path=["response"])
@@ -140,6 +141,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ pagination=0,
synchronous=False,
)
assert_matches_type(SharedTrialLinkListResponse, shared_trial_link, path=["response"])
diff --git a/tests/api_resources/test_smart_link_postbacks.py b/tests/api_resources/test_smart_link_postbacks.py
index 5a5ea6f9..29c028aa 100644
--- a/tests/api_resources/test_smart_link_postbacks.py
+++ b/tests/api_resources/test_smart_link_postbacks.py
@@ -29,7 +29,7 @@ def test_method_create(self, client: OnlyFansAPI) -> None:
smart_link_postback = client.smart_link_postbacks.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
)
assert_matches_type(SmartLinkPostbackCreateResponse, smart_link_postback, path=["response"])
@@ -39,7 +39,15 @@ def test_method_create_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link_postback = client.smart_link_postbacks.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
+ body='{"click_id":"{click_id}","value":"{amount_gross}"}',
+ headers=[
+ {
+ "name": "Authorization",
+ "value": "Bearer token",
+ }
+ ],
+ http_method="POST",
smart_link_ids=["01JTESTLINK000000000000001"],
)
assert_matches_type(SmartLinkPostbackCreateResponse, smart_link_postback, path=["response"])
@@ -50,7 +58,7 @@ def test_raw_response_create(self, client: OnlyFansAPI) -> None:
response = client.smart_link_postbacks.with_raw_response.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
)
assert response.is_closed is True
@@ -64,7 +72,7 @@ def test_streaming_response_create(self, client: OnlyFansAPI) -> None:
with client.smart_link_postbacks.with_streaming_response.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -115,7 +123,7 @@ def test_method_update(self, client: OnlyFansAPI) -> None:
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
)
assert_matches_type(SmartLinkPostbackUpdateResponse, smart_link_postback, path=["response"])
@@ -126,7 +134,15 @@ def test_method_update_with_all_params(self, client: OnlyFansAPI) -> None:
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
+ body='{"click_id":"{click_id}","value":"{amount_gross}"}',
+ headers=[
+ {
+ "name": "Authorization",
+ "value": "Bearer token",
+ }
+ ],
+ http_method="POST",
smart_link_ids=["01JTESTLINK000000000000001"],
)
assert_matches_type(SmartLinkPostbackUpdateResponse, smart_link_postback, path=["response"])
@@ -138,7 +154,7 @@ def test_raw_response_update(self, client: OnlyFansAPI) -> None:
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
)
assert response.is_closed is True
@@ -153,7 +169,7 @@ def test_streaming_response_update(self, client: OnlyFansAPI) -> None:
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -237,7 +253,7 @@ async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link_postback = await async_client.smart_link_postbacks.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
)
assert_matches_type(SmartLinkPostbackCreateResponse, smart_link_postback, path=["response"])
@@ -247,7 +263,15 @@ async def test_method_create_with_all_params(self, async_client: AsyncOnlyFansAP
smart_link_postback = await async_client.smart_link_postbacks.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
+ body='{"click_id":"{click_id}","value":"{amount_gross}"}',
+ headers=[
+ {
+ "name": "Authorization",
+ "value": "Bearer token",
+ }
+ ],
+ http_method="POST",
smart_link_ids=["01JTESTLINK000000000000001"],
)
assert_matches_type(SmartLinkPostbackCreateResponse, smart_link_postback, path=["response"])
@@ -258,7 +282,7 @@ async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None
response = await async_client.smart_link_postbacks.with_raw_response.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
)
assert response.is_closed is True
@@ -272,7 +296,7 @@ async def test_streaming_response_create(self, async_client: AsyncOnlyFansAPI) -
async with async_client.smart_link_postbacks.with_streaming_response.create(
conversion_types=["new_subscriber", "new_transaction"],
smart_link_scope="campaign_specific",
- url="https://example.com/postback?click={click_id}&type={conversion_type}&gclid={gclid}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}&gclid={gclid}",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -323,7 +347,7 @@ async def test_method_update(self, async_client: AsyncOnlyFansAPI) -> None:
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
)
assert_matches_type(SmartLinkPostbackUpdateResponse, smart_link_postback, path=["response"])
@@ -334,7 +358,15 @@ async def test_method_update_with_all_params(self, async_client: AsyncOnlyFansAP
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
+ body='{"click_id":"{click_id}","value":"{amount_gross}"}',
+ headers=[
+ {
+ "name": "Authorization",
+ "value": "Bearer token",
+ }
+ ],
+ http_method="POST",
smart_link_ids=["01JTESTLINK000000000000001"],
)
assert_matches_type(SmartLinkPostbackUpdateResponse, smart_link_postback, path=["response"])
@@ -346,7 +378,7 @@ async def test_raw_response_update(self, async_client: AsyncOnlyFansAPI) -> None
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
)
assert response.is_closed is True
@@ -361,7 +393,7 @@ async def test_streaming_response_update(self, async_client: AsyncOnlyFansAPI) -
postback_id=123,
conversion_types=["new_subscriber"],
smart_link_scope="global",
- url="https://example.com/postback?click={click_id}&type={conversion_type}",
+ url="https://example.com/postback?click={external_click_id}&type={conversion_type}",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_smart_links.py b/tests/api_resources/test_smart_links.py
index 267abb61..62344947 100644
--- a/tests/api_resources/test_smart_links.py
+++ b/tests/api_resources/test_smart_links.py
@@ -131,10 +131,11 @@ def test_method_list(self, client: OnlyFansAPI) -> None:
def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list(
account_ids="acct_abc123,acct_def456",
+ filter={"tags": ["hqmoevvvhvcxcpieoxusxgky"]},
limit=50,
- meta_pixel_ids="1,2",
name="Instagram",
offset=0,
+ pixel_ids="1,2",
)
assert_matches_type(SmartLinkListResponse, smart_link, path=["response"])
@@ -206,7 +207,7 @@ def test_path_params_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_clicks(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
)
assert_matches_type(SmartLinkListClicksResponse, smart_link, path=["response"])
@@ -214,7 +215,7 @@ def test_method_list_clicks(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_clicks_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
date_end="2026-01-07T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
include_bots=True,
@@ -228,7 +229,7 @@ def test_method_list_clicks_with_all_params(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_list_clicks(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
)
assert response.is_closed is True
@@ -240,7 +241,7 @@ def test_raw_response_list_clicks(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list_clicks(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -262,7 +263,7 @@ def test_path_params_list_clicks(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_conversions(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
)
assert_matches_type(SmartLinkListConversionsResponse, smart_link, path=["response"])
@@ -270,7 +271,7 @@ def test_method_list_conversions(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_conversions_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
conversion_type="new_transaction",
date_end="2026-01-07T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -286,7 +287,7 @@ def test_method_list_conversions_with_all_params(self, client: OnlyFansAPI) -> N
@parametrize
def test_raw_response_list_conversions(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
)
assert response.is_closed is True
@@ -298,7 +299,7 @@ def test_raw_response_list_conversions(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list_conversions(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -320,7 +321,7 @@ def test_path_params_list_conversions(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_fans(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
)
assert_matches_type(SmartLinkListFansResponse, smart_link, path=["response"])
@@ -328,14 +329,16 @@ def test_method_list_fans(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_fans_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
has_messages=True,
limit=100,
min_messages_sent_by_fan=3,
min_revenue_net=25,
min_tips_net=10,
offset=0,
+ previously_subscribed=True,
sort="-revenue_net",
+ subscribed_using_promo=True,
)
assert_matches_type(SmartLinkListFansResponse, smart_link, path=["response"])
@@ -343,7 +346,7 @@ def test_method_list_fans_with_all_params(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_list_fans(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
)
assert response.is_closed is True
@@ -355,7 +358,7 @@ def test_raw_response_list_fans(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list_fans(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -377,7 +380,7 @@ def test_path_params_list_fans(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_spenders(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
)
assert_matches_type(SmartLinkListSpendersResponse, smart_link, path=["response"])
@@ -385,7 +388,7 @@ def test_method_list_spenders(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_spenders_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
limit=50,
min_spend=1,
offset=0,
@@ -396,7 +399,7 @@ def test_method_list_spenders_with_all_params(self, client: OnlyFansAPI) -> None
@parametrize
def test_raw_response_list_spenders(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
)
assert response.is_closed is True
@@ -408,7 +411,7 @@ def test_raw_response_list_spenders(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list_spenders(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -430,7 +433,7 @@ def test_path_params_list_spenders(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
)
assert smart_link is None
@@ -438,7 +441,7 @@ def test_method_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_cohort_arps_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
revenue_basis="net",
@@ -449,7 +452,7 @@ def test_method_retrieve_cohort_arps_with_all_params(self, client: OnlyFansAPI)
@parametrize
def test_raw_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
)
assert response.is_closed is True
@@ -461,7 +464,7 @@ def test_raw_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -483,7 +486,7 @@ def test_path_params_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_stats(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
)
assert_matches_type(SmartLinkRetrieveStatsResponse, smart_link, path=["response"])
@@ -491,7 +494,7 @@ def test_method_retrieve_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_stats_with_all_params(self, client: OnlyFansAPI) -> None:
smart_link = client.smart_links.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
)
@@ -501,7 +504,7 @@ def test_method_retrieve_stats_with_all_params(self, client: OnlyFansAPI) -> Non
@parametrize
def test_raw_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
response = client.smart_links.with_raw_response.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
)
assert response.is_closed is True
@@ -513,7 +516,7 @@ def test_raw_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
with client.smart_links.with_streaming_response.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -641,10 +644,11 @@ async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list(
account_ids="acct_abc123,acct_def456",
+ filter={"tags": ["hqmoevvvhvcxcpieoxusxgky"]},
limit=50,
- meta_pixel_ids="1,2",
name="Instagram",
offset=0,
+ pixel_ids="1,2",
)
assert_matches_type(SmartLinkListResponse, smart_link, path=["response"])
@@ -716,7 +720,7 @@ async def test_path_params_delete(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_list_clicks(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
)
assert_matches_type(SmartLinkListClicksResponse, smart_link, path=["response"])
@@ -724,7 +728,7 @@ async def test_method_list_clicks(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_list_clicks_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
date_end="2026-01-07T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
include_bots=True,
@@ -738,7 +742,7 @@ async def test_method_list_clicks_with_all_params(self, async_client: AsyncOnlyF
@parametrize
async def test_raw_response_list_clicks(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
)
assert response.is_closed is True
@@ -750,7 +754,7 @@ async def test_raw_response_list_clicks(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_streaming_response_list_clicks(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.list_clicks(
- smart_link_id="illum",
+ smart_link_id="eum",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -772,7 +776,7 @@ async def test_path_params_list_clicks(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_method_list_conversions(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
)
assert_matches_type(SmartLinkListConversionsResponse, smart_link, path=["response"])
@@ -780,7 +784,7 @@ async def test_method_list_conversions(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_method_list_conversions_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
conversion_type="new_transaction",
date_end="2026-01-07T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -796,7 +800,7 @@ async def test_method_list_conversions_with_all_params(self, async_client: Async
@parametrize
async def test_raw_response_list_conversions(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
)
assert response.is_closed is True
@@ -808,7 +812,7 @@ async def test_raw_response_list_conversions(self, async_client: AsyncOnlyFansAP
@parametrize
async def test_streaming_response_list_conversions(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.list_conversions(
- smart_link_id="fugiat",
+ smart_link_id="quia",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -830,7 +834,7 @@ async def test_path_params_list_conversions(self, async_client: AsyncOnlyFansAPI
@parametrize
async def test_method_list_fans(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
)
assert_matches_type(SmartLinkListFansResponse, smart_link, path=["response"])
@@ -838,14 +842,16 @@ async def test_method_list_fans(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_list_fans_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
has_messages=True,
limit=100,
min_messages_sent_by_fan=3,
min_revenue_net=25,
min_tips_net=10,
offset=0,
+ previously_subscribed=True,
sort="-revenue_net",
+ subscribed_using_promo=True,
)
assert_matches_type(SmartLinkListFansResponse, smart_link, path=["response"])
@@ -853,7 +859,7 @@ async def test_method_list_fans_with_all_params(self, async_client: AsyncOnlyFan
@parametrize
async def test_raw_response_list_fans(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
)
assert response.is_closed is True
@@ -865,7 +871,7 @@ async def test_raw_response_list_fans(self, async_client: AsyncOnlyFansAPI) -> N
@parametrize
async def test_streaming_response_list_fans(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.list_fans(
- smart_link_id="autem",
+ smart_link_id="totam",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -887,7 +893,7 @@ async def test_path_params_list_fans(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_method_list_spenders(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
)
assert_matches_type(SmartLinkListSpendersResponse, smart_link, path=["response"])
@@ -895,7 +901,7 @@ async def test_method_list_spenders(self, async_client: AsyncOnlyFansAPI) -> Non
@parametrize
async def test_method_list_spenders_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
limit=50,
min_spend=1,
offset=0,
@@ -906,7 +912,7 @@ async def test_method_list_spenders_with_all_params(self, async_client: AsyncOnl
@parametrize
async def test_raw_response_list_spenders(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
)
assert response.is_closed is True
@@ -918,7 +924,7 @@ async def test_raw_response_list_spenders(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_streaming_response_list_spenders(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.list_spenders(
- smart_link_id="cum",
+ smart_link_id="enim",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -940,7 +946,7 @@ async def test_path_params_list_spenders(self, async_client: AsyncOnlyFansAPI) -
@parametrize
async def test_method_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
)
assert smart_link is None
@@ -948,7 +954,7 @@ async def test_method_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_method_retrieve_cohort_arps_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
revenue_basis="net",
@@ -959,7 +965,7 @@ async def test_method_retrieve_cohort_arps_with_all_params(self, async_client: A
@parametrize
async def test_raw_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
)
assert response.is_closed is True
@@ -971,7 +977,7 @@ async def test_raw_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFa
@parametrize
async def test_streaming_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.retrieve_cohort_arps(
- smart_link_id="consequatur",
+ smart_link_id="beatae",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -993,7 +999,7 @@ async def test_path_params_retrieve_cohort_arps(self, async_client: AsyncOnlyFan
@parametrize
async def test_method_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
)
assert_matches_type(SmartLinkRetrieveStatsResponse, smart_link, path=["response"])
@@ -1001,7 +1007,7 @@ async def test_method_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_method_retrieve_stats_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
smart_link = await async_client.smart_links.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
)
@@ -1011,7 +1017,7 @@ async def test_method_retrieve_stats_with_all_params(self, async_client: AsyncOn
@parametrize
async def test_raw_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.smart_links.with_raw_response.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
)
assert response.is_closed is True
@@ -1023,7 +1029,7 @@ async def test_raw_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_streaming_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.smart_links.with_streaming_response.retrieve_stats(
- smart_link_id="et",
+ smart_link_id="nisi",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_statistics.py b/tests/api_resources/test_statistics.py
index 664e818b..65697c2c 100644
--- a/tests/api_resources/test_statistics.py
+++ b/tests/api_resources/test_statistics.py
@@ -24,6 +24,14 @@ class TestStatistics:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_calculate_total_transactions(self, client: OnlyFansAPI) -> None:
+ statistic = client.statistics.calculate_total_transactions(
+ account="acct_XXXXXXXXXXXXXXX",
+ )
+ assert_matches_type(StatisticCalculateTotalTransactionsResponse, statistic, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_calculate_total_transactions_with_all_params(self, client: OnlyFansAPI) -> None:
statistic = client.statistics.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
end_date="2025-03-31 23:59:59",
@@ -36,8 +44,6 @@ def test_method_calculate_total_transactions(self, client: OnlyFansAPI) -> None:
def test_raw_response_calculate_total_transactions(self, client: OnlyFansAPI) -> None:
response = client.statistics.with_raw_response.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
)
assert response.is_closed is True
@@ -50,8 +56,6 @@ def test_raw_response_calculate_total_transactions(self, client: OnlyFansAPI) ->
def test_streaming_response_calculate_total_transactions(self, client: OnlyFansAPI) -> None:
with client.statistics.with_streaming_response.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -67,8 +71,6 @@ def test_path_params_calculate_total_transactions(self, client: OnlyFansAPI) ->
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.statistics.with_raw_response.calculate_total_transactions(
account="",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -142,6 +144,7 @@ def test_method_get_subscriber_metrics_with_all_params(self, client: OnlyFansAPI
end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
detailed=False,
+ detailed_type="total",
)
assert_matches_type(StatisticGetSubscriberMetricsResponse, statistic, path=["response"])
@@ -194,6 +197,14 @@ class TestAsyncStatistics:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_calculate_total_transactions(self, async_client: AsyncOnlyFansAPI) -> None:
+ statistic = await async_client.statistics.calculate_total_transactions(
+ account="acct_XXXXXXXXXXXXXXX",
+ )
+ assert_matches_type(StatisticCalculateTotalTransactionsResponse, statistic, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_calculate_total_transactions_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
statistic = await async_client.statistics.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
end_date="2025-03-31 23:59:59",
@@ -206,8 +217,6 @@ async def test_method_calculate_total_transactions(self, async_client: AsyncOnly
async def test_raw_response_calculate_total_transactions(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.statistics.with_raw_response.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
)
assert response.is_closed is True
@@ -220,8 +229,6 @@ async def test_raw_response_calculate_total_transactions(self, async_client: Asy
async def test_streaming_response_calculate_total_transactions(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.statistics.with_streaming_response.calculate_total_transactions(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -237,8 +244,6 @@ async def test_path_params_calculate_total_transactions(self, async_client: Asyn
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.statistics.with_raw_response.calculate_total_transactions(
account="",
- end_date="2025-03-31 23:59:59",
- start_date="2025-01-01 00:00:00",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -312,6 +317,7 @@ async def test_method_get_subscriber_metrics_with_all_params(self, async_client:
end_date="2025-03-31 23:59:59",
start_date="2025-01-01 00:00:00",
detailed=False,
+ detailed_type="total",
)
assert_matches_type(StatisticGetSubscriberMetricsResponse, statistic, path=["response"])
diff --git a/tests/api_resources/test_stored.py b/tests/api_resources/test_stored.py
index 39aab6dd..6054e9d6 100644
--- a/tests/api_resources/test_stored.py
+++ b/tests/api_resources/test_stored.py
@@ -36,8 +36,8 @@ def test_method_list_shared_tracking_links_with_all_params(self, client: OnlyFan
stored = client.stored.list_shared_tracking_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "search": "wawukmfhpsfhwlhgdjcyu",
- "tags": ["iizfurnvqqubrcpiuiou"],
+ "search": "etpxkefmygguhwtxlclwp",
+ "tags": ["mskbijtxogqcuqlxz"],
},
limit=10,
offset=0,
@@ -92,8 +92,8 @@ def test_method_list_shared_trial_links_with_all_params(self, client: OnlyFansAP
stored = client.stored.list_shared_trial_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "search": "wqhvnrc",
- "tags": ["uul"],
+ "search": "zzpcveugjmw",
+ "tags": ["yjegxgarvpgvqppuoeqik"],
},
limit=10,
offset=0,
@@ -148,9 +148,9 @@ def test_method_list_tracking_links_with_all_params(self, client: OnlyFansAPI) -
stored = client.stored.list_tracking_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "include_smart_links": False,
- "search": "pbtzgckzvatqptslffi",
- "tags": ["retewknszoajldmmjdmbfwi"],
+ "include_smart_links": True,
+ "search": "nfjcbmlmeumt",
+ "tags": ["bmbydwjli"],
},
limit=10,
offset=0,
@@ -206,8 +206,8 @@ def test_method_list_trial_links_with_all_params(self, client: OnlyFansAPI) -> N
account="acct_XXXXXXXXXXXXXXX",
filter={
"include_smart_links": False,
- "search": "aazxbzoyffqvxas",
- "tags": ["mbztc"],
+ "search": "lifift",
+ "tags": ["gsmh"],
},
limit=10,
offset=0,
@@ -268,8 +268,8 @@ async def test_method_list_shared_tracking_links_with_all_params(self, async_cli
stored = await async_client.stored.list_shared_tracking_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "search": "wawukmfhpsfhwlhgdjcyu",
- "tags": ["iizfurnvqqubrcpiuiou"],
+ "search": "etpxkefmygguhwtxlclwp",
+ "tags": ["mskbijtxogqcuqlxz"],
},
limit=10,
offset=0,
@@ -324,8 +324,8 @@ async def test_method_list_shared_trial_links_with_all_params(self, async_client
stored = await async_client.stored.list_shared_trial_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "search": "wqhvnrc",
- "tags": ["uul"],
+ "search": "zzpcveugjmw",
+ "tags": ["yjegxgarvpgvqppuoeqik"],
},
limit=10,
offset=0,
@@ -380,9 +380,9 @@ async def test_method_list_tracking_links_with_all_params(self, async_client: As
stored = await async_client.stored.list_tracking_links(
account="acct_XXXXXXXXXXXXXXX",
filter={
- "include_smart_links": False,
- "search": "pbtzgckzvatqptslffi",
- "tags": ["retewknszoajldmmjdmbfwi"],
+ "include_smart_links": True,
+ "search": "nfjcbmlmeumt",
+ "tags": ["bmbydwjli"],
},
limit=10,
offset=0,
@@ -438,8 +438,8 @@ async def test_method_list_trial_links_with_all_params(self, async_client: Async
account="acct_XXXXXXXXXXXXXXX",
filter={
"include_smart_links": False,
- "search": "aazxbzoyffqvxas",
- "tags": ["mbztc"],
+ "search": "lifift",
+ "tags": ["gsmh"],
},
limit=10,
offset=0,
diff --git a/tests/api_resources/test_stories.py b/tests/api_resources/test_stories.py
index 444b68b4..71635ace 100644
--- a/tests/api_resources/test_stories.py
+++ b/tests/api_resources/test_stories.py
@@ -35,6 +35,44 @@ def test_method_create(self, client: OnlyFansAPI) -> None:
)
assert_matches_type(StoryCreateResponse, story, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: OnlyFansAPI) -> None:
+ story = client.stories.create(
+ account="acct_XXXXXXXXXXXXXXX",
+ media_files=["ofapi_media_abc123", "string"],
+ canvas_height=1920,
+ canvas_width=1080,
+ question={
+ "color": "#FF51DC",
+ "height": 160,
+ "left": 25,
+ "text": "Ask me anything!",
+ "top": 30,
+ "width": 257,
+ },
+ texts=[
+ {
+ "text": "New drop today!",
+ "angle": 0,
+ "bg_color": "#FF51DC",
+ "color": "#FFFFFF",
+ "font_family": "ShantellSans",
+ "font_size": 24,
+ "font_weight": 400,
+ "left": 30.5,
+ "scale": 1,
+ "text_align": "center",
+ "text_height": 36,
+ "text_width": 140,
+ "top": 60,
+ "type": "text",
+ "z_index": 8,
+ }
+ ],
+ )
+ assert_matches_type(StoryCreateResponse, story, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_create(self, client: OnlyFansAPI) -> None:
@@ -422,6 +460,44 @@ async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
)
assert_matches_type(StoryCreateResponse, story, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
+ story = await async_client.stories.create(
+ account="acct_XXXXXXXXXXXXXXX",
+ media_files=["ofapi_media_abc123", "string"],
+ canvas_height=1920,
+ canvas_width=1080,
+ question={
+ "color": "#FF51DC",
+ "height": 160,
+ "left": 25,
+ "text": "Ask me anything!",
+ "top": 30,
+ "width": 257,
+ },
+ texts=[
+ {
+ "text": "New drop today!",
+ "angle": 0,
+ "bg_color": "#FF51DC",
+ "color": "#FFFFFF",
+ "font_family": "ShantellSans",
+ "font_size": 24,
+ "font_weight": 400,
+ "left": 30.5,
+ "scale": 1,
+ "text_align": "center",
+ "text_height": 36,
+ "text_width": 140,
+ "top": 60,
+ "type": "text",
+ "z_index": 8,
+ }
+ ],
+ )
+ assert_matches_type(StoryCreateResponse, story, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None:
diff --git a/tests/api_resources/test_tracking_links.py b/tests/api_resources/test_tracking_links.py
index 41243f27..10068e73 100644
--- a/tests/api_resources/test_tracking_links.py
+++ b/tests/api_resources/test_tracking_links.py
@@ -85,7 +85,7 @@ def test_path_params_create(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkRetrieveResponse, tracking_link, path=["response"])
@@ -94,7 +94,7 @@ def test_method_retrieve(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_retrieve(self, client: OnlyFansAPI) -> None:
response = client.tracking_links.with_raw_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -107,7 +107,7 @@ def test_raw_response_retrieve(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: OnlyFansAPI) -> None:
with client.tracking_links.with_streaming_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -123,7 +123,7 @@ def test_streaming_response_retrieve(self, client: OnlyFansAPI) -> None:
def test_path_params_retrieve(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.tracking_links.with_raw_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="",
)
@@ -146,14 +146,15 @@ def test_method_list(self, client: OnlyFansAPI) -> None:
def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.list(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-01-01 00:00:00, now",
- limit=3,
+ end_date="2025-01-31 23:59:59",
+ limit=10,
offset=0,
+ pagination=1,
sort="desc",
sortby="claims",
- start_date="2025-01-01 00:00:00, -30days",
+ start_date="2025-01-01 00:00:00",
synchronous=False,
- with_deleted=False,
+ with_deleted=1,
)
assert_matches_type(TrackingLinkListResponse, tracking_link, path=["response"])
@@ -195,7 +196,7 @@ def test_path_params_list(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_delete(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkDeleteResponse, tracking_link, path=["response"])
@@ -204,7 +205,7 @@ def test_method_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_delete(self, client: OnlyFansAPI) -> None:
response = client.tracking_links.with_raw_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -217,7 +218,7 @@ def test_raw_response_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_delete(self, client: OnlyFansAPI) -> None:
with client.tracking_links.with_streaming_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -233,7 +234,7 @@ def test_streaming_response_delete(self, client: OnlyFansAPI) -> None:
def test_path_params_delete(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.tracking_links.with_raw_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="",
)
@@ -247,7 +248,7 @@ def test_path_params_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_get_cohort_arps(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
)
assert tracking_link is None
@@ -256,7 +257,7 @@ def test_method_get_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_get_cohort_arps_with_all_params(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
@@ -268,7 +269,7 @@ def test_method_get_cohort_arps_with_all_params(self, client: OnlyFansAPI) -> No
@parametrize
def test_raw_response_get_cohort_arps(self, client: OnlyFansAPI) -> None:
response = client.tracking_links.with_raw_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -281,7 +282,7 @@ def test_raw_response_get_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_get_cohort_arps(self, client: OnlyFansAPI) -> None:
with client.tracking_links.with_streaming_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -297,7 +298,7 @@ def test_streaming_response_get_cohort_arps(self, client: OnlyFansAPI) -> None:
def test_path_params_get_cohort_arps(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.tracking_links.with_raw_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="",
)
@@ -311,7 +312,7 @@ def test_path_params_get_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_get_stats(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkGetStatsResponse, tracking_link, path=["response"])
@@ -320,7 +321,7 @@ def test_method_get_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_get_stats_with_all_params(self, client: OnlyFansAPI) -> None:
tracking_link = client.tracking_links.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -331,7 +332,7 @@ def test_method_get_stats_with_all_params(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_get_stats(self, client: OnlyFansAPI) -> None:
response = client.tracking_links.with_raw_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -344,7 +345,7 @@ def test_raw_response_get_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_get_stats(self, client: OnlyFansAPI) -> None:
with client.tracking_links.with_streaming_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -360,7 +361,7 @@ def test_streaming_response_get_stats(self, client: OnlyFansAPI) -> None:
def test_path_params_get_stats(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.tracking_links.with_raw_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="",
)
@@ -562,7 +563,7 @@ async def test_path_params_create(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkRetrieveResponse, tracking_link, path=["response"])
@@ -571,7 +572,7 @@ async def test_method_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.tracking_links.with_raw_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -584,7 +585,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.tracking_links.with_streaming_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -600,7 +601,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOnlyFansAPI)
async def test_path_params_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.tracking_links.with_raw_response.retrieve(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="",
)
@@ -623,14 +624,15 @@ async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.list(
account="acct_XXXXXXXXXXXXXXX",
- end_date="2025-01-01 00:00:00, now",
- limit=3,
+ end_date="2025-01-31 23:59:59",
+ limit=10,
offset=0,
+ pagination=1,
sort="desc",
sortby="claims",
- start_date="2025-01-01 00:00:00, -30days",
+ start_date="2025-01-01 00:00:00",
synchronous=False,
- with_deleted=False,
+ with_deleted=1,
)
assert_matches_type(TrackingLinkListResponse, tracking_link, path=["response"])
@@ -672,7 +674,7 @@ async def test_path_params_list(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_delete(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkDeleteResponse, tracking_link, path=["response"])
@@ -681,7 +683,7 @@ async def test_method_delete(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_delete(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.tracking_links.with_raw_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -694,7 +696,7 @@ async def test_raw_response_delete(self, async_client: AsyncOnlyFansAPI) -> None
@parametrize
async def test_streaming_response_delete(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.tracking_links.with_streaming_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -710,7 +712,7 @@ async def test_streaming_response_delete(self, async_client: AsyncOnlyFansAPI) -
async def test_path_params_delete(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.tracking_links.with_raw_response.delete(
- tracking_link_id="consectetur",
+ tracking_link_id="quidem",
account="",
)
@@ -724,7 +726,7 @@ async def test_path_params_delete(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_get_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
)
assert tracking_link is None
@@ -733,7 +735,7 @@ async def test_method_get_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> N
@parametrize
async def test_method_get_cohort_arps_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
@@ -745,7 +747,7 @@ async def test_method_get_cohort_arps_with_all_params(self, async_client: AsyncO
@parametrize
async def test_raw_response_get_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.tracking_links.with_raw_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -758,7 +760,7 @@ async def test_raw_response_get_cohort_arps(self, async_client: AsyncOnlyFansAPI
@parametrize
async def test_streaming_response_get_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.tracking_links.with_streaming_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -774,7 +776,7 @@ async def test_streaming_response_get_cohort_arps(self, async_client: AsyncOnlyF
async def test_path_params_get_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.tracking_links.with_raw_response.get_cohort_arps(
- tracking_link_id="ratione",
+ tracking_link_id="quasi",
account="",
)
@@ -788,7 +790,7 @@ async def test_path_params_get_cohort_arps(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_method_get_stats(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrackingLinkGetStatsResponse, tracking_link, path=["response"])
@@ -797,7 +799,7 @@ async def test_method_get_stats(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_get_stats_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
tracking_link = await async_client.tracking_links.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -808,7 +810,7 @@ async def test_method_get_stats_with_all_params(self, async_client: AsyncOnlyFan
@parametrize
async def test_raw_response_get_stats(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.tracking_links.with_raw_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -821,7 +823,7 @@ async def test_raw_response_get_stats(self, async_client: AsyncOnlyFansAPI) -> N
@parametrize
async def test_streaming_response_get_stats(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.tracking_links.with_streaming_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -837,7 +839,7 @@ async def test_streaming_response_get_stats(self, async_client: AsyncOnlyFansAPI
async def test_path_params_get_stats(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.tracking_links.with_raw_response.get_stats(
- tracking_link_id="reiciendis",
+ tracking_link_id="ut",
account="",
)
diff --git a/tests/api_resources/test_transactions.py b/tests/api_resources/test_transactions.py
index 8e785c06..9ce059f8 100644
--- a/tests/api_resources/test_transactions.py
+++ b/tests/api_resources/test_transactions.py
@@ -32,7 +32,7 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
limit="limit",
marker="1739155047",
- start_date="2025-01-01 00:00:00, -30days",
+ start_date="2025-01-01 00:00:00",
tips_source="post_all",
type="tips",
)
@@ -93,7 +93,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
account="acct_XXXXXXXXXXXXXXX",
limit="limit",
marker="1739155047",
- start_date="2025-01-01 00:00:00, -30days",
+ start_date="2025-01-01 00:00:00",
tips_source="post_all",
type="tips",
)
diff --git a/tests/api_resources/test_trial_links.py b/tests/api_resources/test_trial_links.py
index 2b6fc57c..b29b3257 100644
--- a/tests/api_resources/test_trial_links.py
+++ b/tests/api_resources/test_trial_links.py
@@ -96,7 +96,7 @@ def test_path_params_create(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkRetrieveResponse, trial_link, path=["response"])
@@ -105,7 +105,7 @@ def test_method_retrieve(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_retrieve(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -118,7 +118,7 @@ def test_raw_response_retrieve(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -134,7 +134,7 @@ def test_streaming_response_retrieve(self, client: OnlyFansAPI) -> None:
def test_path_params_retrieve(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="",
)
@@ -149,8 +149,6 @@ def test_path_params_retrieve(self, client: OnlyFansAPI) -> None:
def test_method_list(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
)
assert_matches_type(TrialLinkListResponse, trial_link, path=["response"])
@@ -159,10 +157,12 @@ def test_method_list(self, client: OnlyFansAPI) -> None:
def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.list(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-01-31 23:59:59",
+ field="create_date",
limit=10,
offset=0,
- field="create_date",
sort="desc",
+ start_date="2025-01-01 00:00:00",
synchronous=False,
)
assert_matches_type(TrialLinkListResponse, trial_link, path=["response"])
@@ -172,8 +172,6 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
def test_raw_response_list(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
)
assert response.is_closed is True
@@ -186,8 +184,6 @@ def test_raw_response_list(self, client: OnlyFansAPI) -> None:
def test_streaming_response_list(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -203,15 +199,13 @@ def test_path_params_list(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.list(
account="",
- limit=10,
- offset=0,
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_delete(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkDeleteResponse, trial_link, path=["response"])
@@ -220,7 +214,7 @@ def test_method_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_delete(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -233,7 +227,7 @@ def test_raw_response_delete(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_delete(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -249,7 +243,7 @@ def test_streaming_response_delete(self, client: OnlyFansAPI) -> None:
def test_path_params_delete(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="",
)
@@ -327,7 +321,7 @@ def test_path_params_list_spenders(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_list_subscribers(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -338,7 +332,7 @@ def test_method_list_subscribers(self, client: OnlyFansAPI) -> None:
@parametrize
def test_raw_response_list_subscribers(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -353,7 +347,7 @@ def test_raw_response_list_subscribers(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_list_subscribers(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -371,7 +365,7 @@ def test_streaming_response_list_subscribers(self, client: OnlyFansAPI) -> None:
def test_path_params_list_subscribers(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="",
limit=10,
offset=0,
@@ -389,7 +383,7 @@ def test_path_params_list_subscribers(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
)
assert trial_link is None
@@ -398,7 +392,7 @@ def test_method_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_cohort_arps_with_all_params(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
@@ -410,7 +404,7 @@ def test_method_retrieve_cohort_arps_with_all_params(self, client: OnlyFansAPI)
@parametrize
def test_raw_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -423,7 +417,7 @@ def test_raw_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -439,7 +433,7 @@ def test_streaming_response_retrieve_cohort_arps(self, client: OnlyFansAPI) -> N
def test_path_params_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="",
)
@@ -453,7 +447,7 @@ def test_path_params_retrieve_cohort_arps(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_stats(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkRetrieveStatsResponse, trial_link, path=["response"])
@@ -462,7 +456,7 @@ def test_method_retrieve_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_method_retrieve_stats_with_all_params(self, client: OnlyFansAPI) -> None:
trial_link = client.trial_links.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -473,7 +467,7 @@ def test_method_retrieve_stats_with_all_params(self, client: OnlyFansAPI) -> Non
@parametrize
def test_raw_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
response = client.trial_links.with_raw_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -486,7 +480,7 @@ def test_raw_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
@parametrize
def test_streaming_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
with client.trial_links.with_streaming_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -502,7 +496,7 @@ def test_streaming_response_retrieve_stats(self, client: OnlyFansAPI) -> None:
def test_path_params_retrieve_stats(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.trial_links.with_raw_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="",
)
@@ -589,7 +583,7 @@ async def test_path_params_create(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_method_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkRetrieveResponse, trial_link, path=["response"])
@@ -598,7 +592,7 @@ async def test_method_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -611,7 +605,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -627,7 +621,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncOnlyFansAPI)
async def test_path_params_retrieve(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.retrieve(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="",
)
@@ -642,8 +636,6 @@ async def test_path_params_retrieve(self, async_client: AsyncOnlyFansAPI) -> Non
async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
)
assert_matches_type(TrialLinkListResponse, trial_link, path=["response"])
@@ -652,10 +644,12 @@ async def test_method_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.list(
account="acct_XXXXXXXXXXXXXXX",
+ end_date="2025-01-31 23:59:59",
+ field="create_date",
limit=10,
offset=0,
- field="create_date",
sort="desc",
+ start_date="2025-01-01 00:00:00",
synchronous=False,
)
assert_matches_type(TrialLinkListResponse, trial_link, path=["response"])
@@ -665,8 +659,6 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
)
assert response.is_closed is True
@@ -679,8 +671,6 @@ async def test_raw_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_streaming_response_list(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.list(
account="acct_XXXXXXXXXXXXXXX",
- limit=10,
- offset=0,
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -696,15 +686,13 @@ async def test_path_params_list(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.list(
account="",
- limit=10,
- offset=0,
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_delete(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkDeleteResponse, trial_link, path=["response"])
@@ -713,7 +701,7 @@ async def test_method_delete(self, async_client: AsyncOnlyFansAPI) -> None:
@parametrize
async def test_raw_response_delete(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -726,7 +714,7 @@ async def test_raw_response_delete(self, async_client: AsyncOnlyFansAPI) -> None
@parametrize
async def test_streaming_response_delete(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -742,7 +730,7 @@ async def test_streaming_response_delete(self, async_client: AsyncOnlyFansAPI) -
async def test_path_params_delete(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.delete(
- trial_link_id="quisquam",
+ trial_link_id="veniam",
account="",
)
@@ -820,7 +808,7 @@ async def test_path_params_list_spenders(self, async_client: AsyncOnlyFansAPI) -
@parametrize
async def test_method_list_subscribers(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -831,7 +819,7 @@ async def test_method_list_subscribers(self, async_client: AsyncOnlyFansAPI) ->
@parametrize
async def test_raw_response_list_subscribers(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -846,7 +834,7 @@ async def test_raw_response_list_subscribers(self, async_client: AsyncOnlyFansAP
@parametrize
async def test_streaming_response_list_subscribers(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
@@ -864,7 +852,7 @@ async def test_streaming_response_list_subscribers(self, async_client: AsyncOnly
async def test_path_params_list_subscribers(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.list_subscribers(
- trial_link_id="ut",
+ trial_link_id="quaerat",
account="",
limit=10,
offset=0,
@@ -882,7 +870,7 @@ async def test_path_params_list_subscribers(self, async_client: AsyncOnlyFansAPI
@parametrize
async def test_method_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
)
assert trial_link is None
@@ -891,7 +879,7 @@ async def test_method_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_method_retrieve_cohort_arps_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
acquisition_end="2026-01-31T23:59:59Z",
acquisition_start="2026-01-01T00:00:00Z",
@@ -903,7 +891,7 @@ async def test_method_retrieve_cohort_arps_with_all_params(self, async_client: A
@parametrize
async def test_raw_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -916,7 +904,7 @@ async def test_raw_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFa
@parametrize
async def test_streaming_response_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -932,7 +920,7 @@ async def test_streaming_response_retrieve_cohort_arps(self, async_client: Async
async def test_path_params_retrieve_cohort_arps(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.retrieve_cohort_arps(
- trial_link_id="sapiente",
+ trial_link_id="deleniti",
account="",
)
@@ -946,7 +934,7 @@ async def test_path_params_retrieve_cohort_arps(self, async_client: AsyncOnlyFan
@parametrize
async def test_method_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
assert_matches_type(TrialLinkRetrieveStatsResponse, trial_link, path=["response"])
@@ -955,7 +943,7 @@ async def test_method_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> No
@parametrize
async def test_method_retrieve_stats_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
trial_link = await async_client.trial_links.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
date_end="2026-01-31T23:59:59Z",
date_start="2026-01-01T00:00:00Z",
@@ -966,7 +954,7 @@ async def test_method_retrieve_stats_with_all_params(self, async_client: AsyncOn
@parametrize
async def test_raw_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.trial_links.with_raw_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
)
@@ -979,7 +967,7 @@ async def test_raw_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI)
@parametrize
async def test_streaming_response_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.trial_links.with_streaming_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="acct_XXXXXXXXXXXXXXX",
) as response:
assert not response.is_closed
@@ -995,7 +983,7 @@ async def test_streaming_response_retrieve_stats(self, async_client: AsyncOnlyFa
async def test_path_params_retrieve_stats(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.trial_links.with_raw_response.retrieve_stats(
- trial_link_id="esse",
+ trial_link_id="quis",
account="",
)
diff --git a/tests/api_resources/test_user_lists.py b/tests/api_resources/test_user_lists.py
index 3675e366..c957caa1 100644
--- a/tests/api_resources/test_user_lists.py
+++ b/tests/api_resources/test_user_lists.py
@@ -28,7 +28,7 @@ class TestUserLists:
def test_method_create(self, client: OnlyFansAPI) -> None:
user_list = client.user_lists.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
)
assert_matches_type(UserListCreateResponse, user_list, path=["response"])
@@ -37,7 +37,7 @@ def test_method_create(self, client: OnlyFansAPI) -> None:
def test_raw_response_create(self, client: OnlyFansAPI) -> None:
response = client.user_lists.with_raw_response.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
)
assert response.is_closed is True
@@ -50,7 +50,7 @@ def test_raw_response_create(self, client: OnlyFansAPI) -> None:
def test_streaming_response_create(self, client: OnlyFansAPI) -> None:
with client.user_lists.with_streaming_response.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -66,7 +66,7 @@ def test_path_params_create(self, client: OnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
client.user_lists.with_raw_response.create(
account="",
- name="qrruxylgb",
+ name="llscmhd",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -204,6 +204,7 @@ def test_method_list_with_all_params(self, client: OnlyFansAPI) -> None:
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ view="queue",
)
assert_matches_type(UserListListResponse, user_list, path=["response"])
@@ -304,7 +305,7 @@ class TestAsyncUserLists:
async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
user_list = await async_client.user_lists.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
)
assert_matches_type(UserListCreateResponse, user_list, path=["response"])
@@ -313,7 +314,7 @@ async def test_method_create(self, async_client: AsyncOnlyFansAPI) -> None:
async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None:
response = await async_client.user_lists.with_raw_response.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
)
assert response.is_closed is True
@@ -326,7 +327,7 @@ async def test_raw_response_create(self, async_client: AsyncOnlyFansAPI) -> None
async def test_streaming_response_create(self, async_client: AsyncOnlyFansAPI) -> None:
async with async_client.user_lists.with_streaming_response.create(
account="acct_XXXXXXXXXXXXXXX",
- name="qrruxylgb",
+ name="llscmhd",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -342,7 +343,7 @@ async def test_path_params_create(self, async_client: AsyncOnlyFansAPI) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account` but received ''"):
await async_client.user_lists.with_raw_response.create(
account="",
- name="qrruxylgb",
+ name="llscmhd",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -480,6 +481,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOnlyFansAPI)
account="acct_XXXXXXXXXXXXXXX",
limit=10,
offset=0,
+ view="queue",
)
assert_matches_type(UserListListResponse, user_list, path=["response"])
diff --git a/tests/api_resources/user_lists/test_users.py b/tests/api_resources/user_lists/test_users.py
index 6bb424fc..b63fd2ef 100644
--- a/tests/api_resources/user_lists/test_users.py
+++ b/tests/api_resources/user_lists/test_users.py
@@ -97,6 +97,17 @@ def test_method_add(self, client: OnlyFansAPI) -> None:
)
assert_matches_type(UserAddResponse, user, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_add_with_all_params(self, client: OnlyFansAPI) -> None:
+ user = client.user_lists.users.add(
+ user_list_id="userListId",
+ account="acct_XXXXXXXXXXXXXXX",
+ ids=["string", "string", "string"],
+ skip_invalid=True,
+ )
+ assert_matches_type(UserAddResponse, user, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_add(self, client: OnlyFansAPI) -> None:
@@ -452,6 +463,17 @@ async def test_method_add(self, async_client: AsyncOnlyFansAPI) -> None:
)
assert_matches_type(UserAddResponse, user, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_add_with_all_params(self, async_client: AsyncOnlyFansAPI) -> None:
+ user = await async_client.user_lists.users.add(
+ user_list_id="userListId",
+ account="acct_XXXXXXXXXXXXXXX",
+ ids=["string", "string", "string"],
+ skip_invalid=True,
+ )
+ assert_matches_type(UserAddResponse, user, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_raw_response_add(self, async_client: AsyncOnlyFansAPI) -> None: