diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 4fb05ff0..b1a01fe2 100644
--- a/.speakeasy/gen.lock
+++ b/.speakeasy/gen.lock
@@ -1,19 +1,19 @@
lockVersion: 2.0.0
id: c48cf606-fb42-4a45-9c23-8f0555307828
management:
- docChecksum: 306a28fc04894c25c30af5e7808a58d0
+ docChecksum: 06126264462b689c48f88ac1ba852482
docVersion: 1.0.0
speakeasyVersion: 1.787.0
generationVersion: 2.914.0
- releaseVersion: 1.3.11
- configChecksum: 0f0bda5d04d5e179f70e2638860fdc17
+ releaseVersion: 1.3.12
+ configChecksum: 430f30d84c52858dd1d454425cf8d9bd
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 1fe47a9d-4490-40b4-9e39-d066c917b993
- pristine_commit_hash: 01475e09a2c374c65dca25b46efd0abbc65ed20e
- pristine_tree_hash: cd9a0d53e416af933de7ada3f974c61635bbb8f9
+ generation_id: f3ffde77-5c91-4a84-8f4b-dd20dfdbcf28
+ pristine_commit_hash: 8a68f1738fdf2914835207adddd522d41f5d8758
+ pristine_tree_hash: 430b4f53eaba7550bc82e9d1e83a38675cda5671
features:
python:
acceptHeaders: 3.0.0
@@ -2490,6 +2490,10 @@ trackedFiles:
id: 73f247dc0e33
last_write_checksum: sha1:30861793800a2851105bfa5b9406520320129f06
pristine_git_object: 18d6a80440f1dc702eae3a3917a53a2def1fca72
+ docs/components/createenduserrequest.mdx:
+ id: e82c759c8be2
+ last_write_checksum: sha1:a91e5f439be4943f1d2012ae04c52d129fb95326
+ pristine_git_object: daaedee3ad25549548155e792662282505bd099e
docs/components/createguardrailrequest.mdx:
id: c1a768f054c0
last_write_checksum: sha1:d32d712d132971b34f6d81d28ff45d22d919f4ac
@@ -2910,6 +2914,14 @@ trackedFiles:
id: 5e4fa96c840d
last_write_checksum: sha1:4d2ccb7fc0d20c8a0b72db3a55a8228169891b6a
pristine_git_object: 72c5b4fb8441c2a4337dc9906fa81b01bb92f126
+ docs/components/enduser.mdx:
+ id: a690fe4da7fa
+ last_write_checksum: sha1:67fae70e3bac87655ed152cf389b9f21b3211e83
+ pristine_git_object: 331116736dabd659c02f4aa9fa23835017b2d043
+ docs/components/enduserresponse.mdx:
+ id: e340b96bf3b4
+ last_write_checksum: sha1:83fbaf74d163f2498007397e3c37f06db8086c0a
+ pristine_git_object: 4b605db127b9e50464b42c8e9650b84f6b36c101
docs/components/enumcapability.mdx:
id: 33c7a0f315d5
last_write_checksum: sha1:08338d742893cb3966cd12cee49a5d80748b3d63
@@ -4114,6 +4126,10 @@ trackedFiles:
id: 1aeb90d09e63
last_write_checksum: sha1:b5d3535ac0e30e1ac1f4f44f3dd17fc8d07aeaff
pristine_git_object: 2df1189da38f979e3ce2bc39c62eb5b79aec3060
+ docs/components/listendusersresponse.mdx:
+ id: 83bf1b522c37
+ last_write_checksum: sha1:0c009062976d9dd800d8e592b85a5796398fd456
+ pristine_git_object: b95cdd819dc02959feefbabf9371ea961ef47175
docs/components/listguardrailsresponse.mdx:
id: ba740952e77b
last_write_checksum: sha1:5a75d264da7e1074ccb5529bf06dce343db5a8da
@@ -7474,6 +7490,10 @@ trackedFiles:
id: 9b4490c340b4
last_write_checksum: sha1:5ca8cef381afdb1c03ce16df023738e163dab13b
pristine_git_object: cad8d3e654b3c1c1b570f80f73f1173a72e17db2
+ docs/components/updateenduserrequest.mdx:
+ id: 42e918f01861
+ last_write_checksum: sha1:cfc96316a62b5df60663ccec298ad23b33c93876
+ pristine_git_object: 72a1c5ade4703a295e533f6e12733f464a21ff65
docs/components/updateguardrailrequest.mdx:
id: 450912b18db6
last_write_checksum: sha1:f0e2aaf8ecb96d8b53a02768ec260472490963cd
@@ -8166,6 +8186,14 @@ trackedFiles:
id: 4f9205ca2bb9
last_write_checksum: sha1:8156e256387b12cc08a5a92f9e9332ec2b35a2af
pristine_git_object: 1218cf960cbc2285120cb399596e0bc73b44aa9f
+ docs/operations/createenduserglobals.mdx:
+ id: edb6cb53a590
+ last_write_checksum: sha1:1ab6518cccfb2d8d62fc3378bb5ccf19f07c8530
+ pristine_git_object: e420bbbee81a1d9392f5249150e4d6823b7bc360
+ docs/operations/createenduserrequest.mdx:
+ id: 36afb465cbb1
+ last_write_checksum: sha1:dd01057e3c354507a3880814b7e12937ad1c143d
+ pristine_git_object: 9448f50842deb5c7b5dcf4c2d5f022a3d43d20d8
docs/operations/createguardrailglobals.mdx:
id: ce6e792df15c
last_write_checksum: sha1:6542508eed5dbd74bf6812b8cc0cc9cfd3157d06
@@ -8382,6 +8410,14 @@ trackedFiles:
id: 5f6e81896314
last_write_checksum: sha1:2927f00b81e9bccb0d19ce46dfd3fdc23475eb4c
pristine_git_object: 7fdac9559bfcf2860dbd533e0d3ae974ab26f193
+ docs/operations/deleteenduserglobals.mdx:
+ id: 17d644a655d0
+ last_write_checksum: sha1:7512fbfbf270ee7c9cff32787917d8a81d05c357
+ pristine_git_object: 07094eff6bf7c06a69ac4181ae000c55a9482dc0
+ docs/operations/deleteenduserrequest.mdx:
+ id: 5033dca978c6
+ last_write_checksum: sha1:f3dc8c200980f206035f781db10d4be74d20f6d6
+ pristine_git_object: ad4cacf77e1ba21cfd6b82ba325b2c4a4d72937c
docs/operations/deletefileglobals.mdx:
id: b95c49d91968
last_write_checksum: sha1:1eaa5442be2df2702baf53f5dddedd40ce930fcc
@@ -8674,6 +8710,14 @@ trackedFiles:
id: 8b6709d01b8b
last_write_checksum: sha1:85dde6bb90c5686384d11484601d8859c0b8fa7e
pristine_git_object: f8fbad096ce3725d56f12a5d6a3ea32a79891c6b
+ docs/operations/getenduserglobals.mdx:
+ id: e8c43375935a
+ last_write_checksum: sha1:254de886f9c34765bce15368509f1fba2b68d5ae
+ pristine_git_object: 9ec66ba16256d22f51356ac3ac0b2195a454f121
+ docs/operations/getenduserrequest.mdx:
+ id: 19de93747569
+ last_write_checksum: sha1:32592160c298cedac111022380ba02f466c88a3d
+ pristine_git_object: 501f7d298695ab0b7eb5ee0aaeffa35dadf6f67c
docs/operations/getfilemetadataglobals.mdx:
id: e4f16f1ce98e
last_write_checksum: sha1:f736518bdebac4aa8c9caf9071e0670885bd83b3
@@ -9018,6 +9062,18 @@ trackedFiles:
id: f8d0c52ac714
last_write_checksum: sha1:259ccd67ebae39f4ab027939482c3e337ba37312
pristine_git_object: 31012e2cfce20ea33c3e4781f8db798e4f33d867
+ docs/operations/listendusersglobals.mdx:
+ id: caf708972b97
+ last_write_checksum: sha1:80d09dcebee7f87784859d0462b2efc3d26fbe95
+ pristine_git_object: 3b3fecc1e477bafabe93350df4bec82cad5ebfe3
+ docs/operations/listendusersrequest.mdx:
+ id: 07d0f1292e9c
+ last_write_checksum: sha1:00fec8ef51775ba9dd3e6c7f8b5f2215e7fd7fd6
+ pristine_git_object: 0dd8516dbc7e33fa177e38f8624978643aa7bba7
+ docs/operations/listendusersresponse.mdx:
+ id: c939c37b2eb5
+ last_write_checksum: sha1:b27d7044dd883f11fcd98d67b234120b13364c81
+ pristine_git_object: d8ac526225636dfdccb8536fd7cd4e1ad4a4afde
docs/operations/listfilesglobals.mdx:
id: 1674db6bdeb2
last_write_checksum: sha1:e387e5f7c8e60d7b5f47d84ccdc1132cc0efc45a
@@ -9554,6 +9610,14 @@ trackedFiles:
id: cef280b21ee9
last_write_checksum: sha1:86da6f664f74203209024032ed6c1281cb696757
pristine_git_object: 546e001df35e2526f0e8bd92a6836be03cf7cc5d
+ docs/operations/updateenduserglobals.mdx:
+ id: 3eab3e5b90d4
+ last_write_checksum: sha1:6f49a3b900d1c12830bda99251ae36da5df7db72
+ pristine_git_object: de504b1ca4a7fee6076860abdc5c200708c68b0f
+ docs/operations/updateenduserrequest.mdx:
+ id: c61c7edc838b
+ last_write_checksum: sha1:bc25b716e93ea4ef8700cf514634924acb715d84
+ pristine_git_object: 62ae0d75e3ef262ff61485f53f9e103316097953
docs/operations/updateguardrailglobals.mdx:
id: e3ce035d5a7c
last_write_checksum: sha1:6dc745162b36e08d38d6ea094282f5c45baf71f2
@@ -9750,6 +9814,10 @@ trackedFiles:
id: 62dfac9f7b71
last_write_checksum: sha1:db7ed18401bcd4afa7382a9793c9ccafb5220497
pristine_git_object: f8cebc2061d7428904766956be45ca70e5519be4
+ docs/sdks/endusers/README.mdx:
+ id: ba369f05185b
+ last_write_checksum: sha1:0eec372c7e75bea130e1cdd6405348dc49bfd938
+ pristine_git_object: 8f4e8760a7ad9ced8023005e8b304f316c116273
docs/sdks/files/README.mdx:
id: 1a0c257e330c
last_write_checksum: sha1:f92d58e58f2ac2048faa8b4420c1663a48e20959
@@ -9844,8 +9912,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:4c6f741c1dc0c7ee0b5c4eb7fbf2b91f2074c7e1
- pristine_git_object: 71e0d5366924fbdaa1cc1cb59ca12cdbe9954ead
+ last_write_checksum: sha1:77b1dff1c45babf177022bcf35a8c487b665c222
+ pristine_git_object: 6372f8443a83c42b0d33f301659afd5af6dc4ade
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -9872,8 +9940,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:f23a121ae5533716c91802589bb6645760fc98a0
- pristine_git_object: 03bc9a3e511f9873149518384a6c238b3c9dae87
+ last_write_checksum: sha1:a5aaa3b13ea037bf135679735cea3c4b3dff7916
+ pristine_git_object: b85f7b325976189a4040ff252699df8bd5c7a23b
src/openrouter/alpha.py:
id: 306c4d93308d
last_write_checksum: sha1:30f55a360f41376ab194b9ea725fe4e001a5ae1a
@@ -9920,8 +9988,8 @@ trackedFiles:
pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1
src/openrouter/components/__init__.py:
id: 81754e97b3f4
- last_write_checksum: sha1:42642b4e0e47e0822eabafb020eff7e5f2c94c38
- pristine_git_object: ada2bdeb1d49520d8348c1691535a0e14be660f6
+ last_write_checksum: sha1:9a9eb742f6674e0bcc5115abb71736a81b5804b8
+ pristine_git_object: 42136dee42b3b7213bbaa9868f39ee5ed4bc08c8
src/openrouter/components/aabenchmarkentry.py:
id: e2e0f0b48c82
last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c
@@ -10970,6 +11038,10 @@ trackedFiles:
id: 2b6c5e13270a
last_write_checksum: sha1:a7a2a40b9ac16a975a4c5ecc8802fc0b7785691c
pristine_git_object: fcfd9d646f216fdbb715cbbaefa4382d75750b79
+ src/openrouter/components/createenduserrequest.py:
+ id: 68e7dcf03498
+ last_write_checksum: sha1:53f7c250769b1bd14e9b5e67f0270790289574e3
+ pristine_git_object: 25623d5f15909380334415605a51f7f6beea9e1c
src/openrouter/components/createguardrailrequest.py:
id: 34d69149fb33
last_write_checksum: sha1:af6fca661fed3b42e547333b14750448c46b43cf
@@ -11150,6 +11222,14 @@ trackedFiles:
id: e935c578fce8
last_write_checksum: sha1:8a9c8184852faf1e3ca9a478e48df41ccac6fc33
pristine_git_object: ed5f8af0c599b1e55bb1939bc1d2aff0aeef610d
+ src/openrouter/components/enduser.py:
+ id: 1fad1ecc5e12
+ last_write_checksum: sha1:8f11cd6a99d28247d4e422a7eb38bb401101852f
+ pristine_git_object: 1b20f1bbc5c0898cf7bb19a2bb268c65a0747a79
+ src/openrouter/components/enduserresponse.py:
+ id: 3da82145da68
+ last_write_checksum: sha1:794963d7fadbbaf7bfb91983d83bec71c9a10556
+ pristine_git_object: 04707ad9a1ba9613db756ec89632d85d836c91d4
src/openrouter/components/enumcapability.py:
id: 1eddd72a17a5
last_write_checksum: sha1:09e366c414f84edb166eeb8e9091e278c15136d6
@@ -11694,6 +11774,10 @@ trackedFiles:
id: 7662d5774bdb
last_write_checksum: sha1:8645389f8ca0cc28969d27c99c3ef6dd6a2fe3d3
pristine_git_object: f62b08917378eab6603f9b780c31a0e561329dc4
+ src/openrouter/components/listendusersresponse.py:
+ id: f4e3d2a1226b
+ last_write_checksum: sha1:131ed7ad8729d2dded869a84ddf83dfd067b06f0
+ pristine_git_object: b2fade2a32b04be83817295407a6b9a43473a81e
src/openrouter/components/listguardrailsresponse.py:
id: 78fbd2689b5d
last_write_checksum: sha1:d3103f2ff7aa2be788ef4aacf6a068497779cca1
@@ -13034,6 +13118,10 @@ trackedFiles:
id: 31338080f7cc
last_write_checksum: sha1:794d77355ae37451076a6b5754c6c8cc77063047
pristine_git_object: a3664695c9722c531f7694851da76e51c2efe4fb
+ src/openrouter/components/updateenduserrequest.py:
+ id: 5613bf6e335a
+ last_write_checksum: sha1:5c92ef6ab64b445ed6c855dc7e06e8df54a1e4bf
+ pristine_git_object: 0a8dcb3fb8d9c0c80159a622246dff4a3110bb1b
src/openrouter/components/updateguardrailrequest.py:
id: 6a557cd822a0
last_write_checksum: sha1:0e5978b49b7a37f48931dd778caf1fc46657b881
@@ -13266,6 +13354,10 @@ trackedFiles:
id: 0374ace39067
last_write_checksum: sha1:0b6b330486e95ed33ccb9849ff7daa11ed2804d9
pristine_git_object: 6f392ba268a36c1101c027f6a2fbf87e2cd68d10
+ src/openrouter/end_users.py:
+ id: d6787489a521
+ last_write_checksum: sha1:bb121c7899ae37fd7c8a897dd524be453816ee79
+ pristine_git_object: 544e6911aca76db7531c73d52d7f0b420a1851f0
src/openrouter/endpoints.py:
id: 465bbf2b7939
last_write_checksum: sha1:a04548ad80c9b1cf8ae1f5dde2e24774865c1eb8
@@ -13436,8 +13528,8 @@ trackedFiles:
pristine_git_object: 8680343bbc90107ae6413bd5686012b1fd75d665
src/openrouter/operations/__init__.py:
id: 9afcea1e7161
- last_write_checksum: sha1:9214c0287f7eb88eee096235ebe428439c308f51
- pristine_git_object: ee19e0cac6af2d20d360c529b6786531ab10b239
+ last_write_checksum: sha1:cf7033fa5a3bc17a7ec8012f693b042afdcb6b4b
+ pristine_git_object: 789d0b8285902141a00adc64f2e5c56352b756cf
src/openrouter/operations/activateprivateendpoint.py:
id: 3b39eec5d66f
last_write_checksum: sha1:9406e6b3d38c82895fd795f637702ef579cc6d36
@@ -13502,6 +13594,10 @@ trackedFiles:
id: fe1160a960e9
last_write_checksum: sha1:c1e7ac31c6ed358390feeef03d91e5917e57d5de
pristine_git_object: 480596964d35ec389350b19b2bf56ac1877960ce
+ src/openrouter/operations/createenduser.py:
+ id: 36f457e15ca4
+ last_write_checksum: sha1:dc2efc0d9bc08d4f397412b232bd1f3f3943646a
+ pristine_git_object: 9a40dbfcc416018a82011457c1f795a671f6d642
src/openrouter/operations/createguardrail.py:
id: 52ed4b2f5903
last_write_checksum: sha1:d4351fdd66f1fa2bedcfc9a974c7f4ff6c68a6bc
@@ -13582,6 +13678,10 @@ trackedFiles:
id: b1b2c6b06913
last_write_checksum: sha1:90aad5198d43e289d99c7b2eb66353de7593a68b
pristine_git_object: 2148ca98c6cde1506783e9c5f2f522226a27e428
+ src/openrouter/operations/deleteenduser.py:
+ id: f17d13ce6e08
+ last_write_checksum: sha1:8bdd5d0135fd346136d447e97a96d0e58004d850
+ pristine_git_object: 34d3359a609a0a2d466af2e182e2e7a67d30f5b4
src/openrouter/operations/deletefile.py:
id: 7035af059141
last_write_checksum: sha1:9eef35ceee470a0dceb64d463ec499a2e8bad9b5
@@ -13678,6 +13778,10 @@ trackedFiles:
id: baf3e38db22c
last_write_checksum: sha1:844575d6a91ab0152ee5f64d14b24afa04a04aeb
pristine_git_object: f6f9e817724dfd60e747f7c35f297c96bedad819
+ src/openrouter/operations/getenduser.py:
+ id: d20b891f0b70
+ last_write_checksum: sha1:8b5a84a6d6782b6afd98d9d195887b23939f9e6d
+ pristine_git_object: ec4817b78ab7619d405586bf192733c11cbb46a1
src/openrouter/operations/getfilemetadata.py:
id: 408c34486769
last_write_checksum: sha1:592b6646b4ff082d8427ea08e79e6b34be490857
@@ -13802,6 +13906,10 @@ trackedFiles:
id: 588bf206e92f
last_write_checksum: sha1:dd1cc08d8779d71a9ad80e0ad764fea72b3fb846
pristine_git_object: f5bd1f67dc835230e6d282e0500cbf3b5781eab4
+ src/openrouter/operations/listendusers.py:
+ id: 5a2a070b97a4
+ last_write_checksum: sha1:57df0a74677bf676dbabd86e10cb653834339725
+ pristine_git_object: 2997608bf4b80c6eaf5ef889f417e26a7ab187a1
src/openrouter/operations/listfiles.py:
id: fd89527f4236
last_write_checksum: sha1:b4a0b5c4b4152ed8c2766afbaf9d9557ceb347f3
@@ -13958,6 +14066,10 @@ trackedFiles:
id: 486f4ea60120
last_write_checksum: sha1:a170382e38c66128bddbe8ea18c034d1350910da
pristine_git_object: cf8b4ee9febb198afe12c27d03c72902eaa8baf0
+ src/openrouter/operations/updateenduser.py:
+ id: 62d2ff1bbd3e
+ last_write_checksum: sha1:ad15bb7939a3306707e6711b06e27bf68fb8cc33
+ pristine_git_object: 2e0d7cce1294b09b88f9e40403362267479b421e
src/openrouter/operations/updateguardrail.py:
id: 6cfb33d7d40c
last_write_checksum: sha1:bf4f6b9899c176fa012acc607556a66d6e85a51b
@@ -14036,8 +14148,8 @@ trackedFiles:
pristine_git_object: a28df9a26e2dd834e5bc8974c3a61d18609c79c0
src/openrouter/sdk.py:
id: ee9846c4c9c5
- last_write_checksum: sha1:61f29c3c30502f852822fa16b2d16d1a778273df
- pristine_git_object: 0a110f2cdff3e7c31e971721166593cc792bc424
+ last_write_checksum: sha1:da0be6fb98b533d46bc081ad07a051dc0b4df355
+ pristine_git_object: 8d7b90d73d3870661ef59982a25f34219d48dd2e
src/openrouter/sdkconfiguration.py:
id: 55773bb98d7c
last_write_checksum: sha1:c01826125c31a8b8bc99d9d679782c8758fae001
@@ -17942,5 +18054,94 @@ examples:
application/json: {"error": {"code": 404, "message": "Resource not found"}}
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ listEndUsers:
+ speakeasy-default-list-end-users:
+ parameters:
+ query:
+ offset: 0
+ limit: 50
+ include_inactive: false
+ responses:
+ "200":
+ application/json: {"data": [{"created_at": "2026-09-16T12:00:00Z", "is_active": true, "updated_at": "2026-09-16T12:00:00Z", "user": "employee_123"}], "total_count": 1}
+ "400":
+ application/json: {"error": {"code": 400, "message": "Invalid request parameters"}}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "500":
+ application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ createEndUser:
+ speakeasy-default-create-end-user:
+ requestBody:
+ application/json: {"user": "employee_123"}
+ responses:
+ "201":
+ application/json: {"data": {"created_at": "2026-09-16T12:00:00Z", "is_active": true, "updated_at": "2026-09-16T12:00:00Z", "user": "employee_123"}}
+ "400":
+ application/json: {"error": {"code": 400, "message": "Invalid request parameters"}}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "409":
+ application/json: {"error": {"code": 409, "message": "Resource conflict. Please try again later."}}
+ "500":
+ application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ deleteEndUser:
+ speakeasy-default-delete-end-user:
+ parameters:
+ path:
+ user: "employee_123"
+ responses:
+ "400":
+ application/json: {"error": {"code": 400, "message": "Invalid request parameters"}}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "500":
+ application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ getEndUser:
+ speakeasy-default-get-end-user:
+ parameters:
+ path:
+ user: "employee_123"
+ responses:
+ "200":
+ application/json: {"data": {"created_at": "2026-09-16T12:00:00Z", "is_active": true, "updated_at": "2026-09-16T12:00:00Z", "user": "employee_123"}}
+ "400":
+ application/json: {"error": {"code": 400, "message": "Invalid request parameters"}}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "500":
+ application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ updateEndUser:
+ speakeasy-default-update-end-user:
+ parameters:
+ path:
+ user: "employee_123"
+ requestBody:
+ application/json: {"is_active": true}
+ responses:
+ "200":
+ application/json: {"data": {"created_at": "2026-09-16T12:00:00Z", "is_active": true, "updated_at": "2026-09-16T12:00:00Z", "user": "employee_123"}}
+ "400":
+ application/json: {"error": {"code": 400, "message": "Invalid request parameters"}}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "500":
+ application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
examplesVersion: 1.0.2
-releaseNotes: "## Python SDK Changes:\n* `open_router.batch.create_batches()`: `response.results[].response.body` **Changed**\n* `open_router.batch.get_batches()`: `response.results[].response.body` **Changed**\n* `open_router.chat.send()`: \n * `request.plugins[].union(alignment)` **Added**\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.plugins[].union(alignment)` **Added**\n* `open_router.presets.create_presets_messages()`: \n * `request.plugins[].union(alignment)` **Added**\n* `open_router.presets.create_presets_responses()`: \n * `request.plugins[].union(alignment)` **Added**\n* `open_router.responses.send()`: \n * `request.plugins[].union(alignment)` **Added**\n * `response` **Changed**\n* `open_router.beta.responses.send()`: \n * `request.plugins[].union(alignment)` **Added**\n * `response` **Changed**\n"
+releaseNotes: |
+ ## Python SDK Changes:
+ * `open_router.end_users.list()`: **Added**
+ * `open_router.end_users.create()`: **Added**
+ * `open_router.end_users.delete()`: **Added**
+ * `open_router.end_users.get()`: **Added**
+ * `open_router.end_users.update()`: **Added**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index 81c33a60..28e7bd1d 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -36,7 +36,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.3.11
+ version: 1.3.12
additionalDependencies:
dev: {}
main: {}
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index c347c164..69ec9b43 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -9340,6 +9340,21 @@ components:
- 'response'
- 'sequence_number'
type: 'object'
+ CreateEndUserRequest:
+ additionalProperties: false
+ example:
+ user: 'employee_123'
+ properties:
+ user:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ required:
+ - 'user'
+ type: 'object'
CreateGuardrailRequest:
example:
allowed_models: null
@@ -10821,6 +10836,54 @@ components:
example: 0
type: 'integer'
x-speakeasy-unknown-values: allow
+ EndUser:
+ additionalProperties: false
+ example:
+ created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ properties:
+ created_at:
+ description: 'Registration creation time.'
+ example: '2026-09-16T12:00:00Z'
+ format: 'date-time'
+ type: 'string'
+ is_active:
+ description: 'Whether this registration is active. Not an inference authorization decision.'
+ example: true
+ type: 'boolean'
+ updated_at:
+ description: 'Last registration lifecycle update time.'
+ example: '2026-09-16T12:00:00Z'
+ format: 'date-time'
+ type: 'string'
+ user:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ required:
+ - 'user'
+ - 'is_active'
+ - 'created_at'
+ - 'updated_at'
+ type: 'object'
+ EndUserResponse:
+ example:
+ data:
+ created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ properties:
+ data:
+ $ref: '#/components/schemas/EndUser'
+ required:
+ - 'data'
+ type: 'object'
EnumCapability:
description: 'A parameter that accepts one of a discrete set of string values.'
example:
@@ -15595,6 +15658,27 @@ components:
- 'architecture'
- 'endpoints'
type: 'object'
+ ListEndUsersResponse:
+ example:
+ data:
+ - created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ total_count: 1
+ properties:
+ data:
+ items:
+ $ref: '#/components/schemas/EndUser'
+ type: 'array'
+ total_count:
+ description: 'Number of registrations matching the filters before pagination.'
+ example: 1
+ type: 'integer'
+ required:
+ - 'data'
+ - 'total_count'
+ type: 'object'
ListGuardrailsResponse:
example:
data:
@@ -30996,6 +31080,18 @@ components:
required:
- 'data'
type: 'object'
+ UpdateEndUserRequest:
+ additionalProperties: false
+ example:
+ is_active: true
+ properties:
+ is_active:
+ description: 'Registration state only; does not enforce inference access.'
+ example: true
+ type: 'boolean'
+ required:
+ - 'is_active'
+ type: 'object'
UpdateGuardrailRequest:
example:
description: 'Updated description'
@@ -37684,6 +37780,425 @@ paths:
- $ref: "#/components/parameters/AppIdentifier"
- $ref: "#/components/parameters/AppDisplayName"
- $ref: "#/components/parameters/AppCategories"
+ /end-users:
+ get:
+ description: 'List registrations belonging to the authenticated organization. Inactive registrations are excluded by default. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ operationId: 'listEndUsers'
+ parameters:
+ - description: 'Number of records to skip for pagination'
+ in: 'query'
+ name: 'offset'
+ required: false
+ schema:
+ default: 0
+ description: 'Number of records to skip for pagination'
+ example: 0
+ minimum: 0
+ type:
+ - 'integer'
+ - 'null'
+ nullable: false
+ - description: 'Maximum number of records to return (max 100)'
+ in: 'query'
+ name: 'limit'
+ required: false
+ schema:
+ default: 50
+ description: 'Maximum number of records to return (max 100)'
+ example: 50
+ maximum: 100
+ minimum: 1
+ type: 'integer'
+ - description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ in: 'query'
+ name: 'user'
+ required: false
+ schema:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ - description: 'Include deactivated registrations.'
+ in: 'query'
+ name: 'include_inactive'
+ required: false
+ schema:
+ default: false
+ description: 'Include deactivated registrations.'
+ example: false
+ type: 'boolean'
+ responses:
+ '200':
+ content:
+ application/json:
+ example:
+ data:
+ - created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ total_count: 1
+ schema:
+ $ref: '#/components/schemas/ListEndUsersResponse'
+ description: 'Matching registrations and their total count.'
+ '400':
+ content:
+ application/json:
+ example:
+ error:
+ code: 400
+ message: 'Invalid request parameters'
+ schema:
+ $ref: '#/components/schemas/BadRequestResponse'
+ description: 'Bad Request - Invalid request parameters or malformed input'
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: 'Missing Authentication header'
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: 'Unauthorized - Authentication required or invalid credentials'
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: 'Resource not found'
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: 'Not Found - Resource does not exist'
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: 'Internal Server Error'
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: 'Internal Server Error - Unexpected server error'
+ summary: 'List registered end users'
+ tags:
+ - 'End Users'
+ x-speakeasy-name-override: 'list'
+ x-speakeasy-pagination:
+ inputs:
+ - in: 'parameters'
+ name: 'offset'
+ type: 'offset'
+ - in: 'parameters'
+ name: 'limit'
+ type: 'limit'
+ outputs:
+ results: '$.data'
+ type: 'offsetLimit'
+ post:
+ description: 'Register a caller-supplied tracking ID under the authenticated organization. No login account, policy, or credentials are created. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ operationId: 'createEndUser'
+ requestBody:
+ content:
+ application/json:
+ example:
+ user: 'employee_123'
+ schema:
+ $ref: '#/components/schemas/CreateEndUserRequest'
+ required: true
+ responses:
+ '201':
+ content:
+ application/json:
+ example:
+ data:
+ created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ schema:
+ $ref: '#/components/schemas/EndUserResponse'
+ description: 'The registered end user. No generated public identifier is returned.'
+ '400':
+ content:
+ application/json:
+ example:
+ error:
+ code: 400
+ message: 'Invalid request parameters'
+ schema:
+ $ref: '#/components/schemas/BadRequestResponse'
+ description: 'Bad Request - Invalid request parameters or malformed input'
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: 'Missing Authentication header'
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: 'Unauthorized - Authentication required or invalid credentials'
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: 'Resource not found'
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: 'Not Found - Resource does not exist'
+ '409':
+ content:
+ application/json:
+ example:
+ error:
+ code: 409
+ message: 'This tracking ID is already registered'
+ schema:
+ $ref: '#/components/schemas/ConflictResponse'
+ description: 'The tracking ID is already registered in this organization, active or not.'
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: 'Internal Server Error'
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: 'Internal Server Error - Unexpected server error'
+ summary: 'Register an end user'
+ tags:
+ - 'End Users'
+ x-speakeasy-name-override: 'create'
+ parameters:
+ - $ref: "#/components/parameters/AppIdentifier"
+ - $ref: "#/components/parameters/AppDisplayName"
+ - $ref: "#/components/parameters/AppCategories"
+ /end-users/{user}:
+ delete:
+ description: 'Soft-deactivate a registration while retaining its tracking ID. Repeat deactivation succeeds. This does not block inference; reactivate through PATCH. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ operationId: 'deleteEndUser'
+ parameters:
+ - description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ in: 'path'
+ name: 'user'
+ required: true
+ schema:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ responses:
+ '204':
+ description: 'Registration is inactive.'
+ '400':
+ content:
+ application/json:
+ example:
+ error:
+ code: 400
+ message: 'Invalid request parameters'
+ schema:
+ $ref: '#/components/schemas/BadRequestResponse'
+ description: 'Bad Request - Invalid request parameters or malformed input'
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: 'Missing Authentication header'
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: 'Unauthorized - Authentication required or invalid credentials'
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: 'Resource not found'
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: 'Not Found - Resource does not exist'
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: 'Internal Server Error'
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: 'Internal Server Error - Unexpected server error'
+ summary: 'Deactivate a registered end user'
+ tags:
+ - 'End Users'
+ x-speakeasy-name-override: 'delete'
+ get:
+ description: 'Retrieve an active or inactive registration by its URL-encoded, caller-supplied tracking ID. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ operationId: 'getEndUser'
+ parameters:
+ - description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ in: 'path'
+ name: 'user'
+ required: true
+ schema:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ responses:
+ '200':
+ content:
+ application/json:
+ example:
+ data:
+ created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ schema:
+ $ref: '#/components/schemas/EndUserResponse'
+ description: 'The registered end user. No generated public identifier is returned.'
+ '400':
+ content:
+ application/json:
+ example:
+ error:
+ code: 400
+ message: 'Invalid request parameters'
+ schema:
+ $ref: '#/components/schemas/BadRequestResponse'
+ description: 'Bad Request - Invalid request parameters or malformed input'
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: 'Missing Authentication header'
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: 'Unauthorized - Authentication required or invalid credentials'
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: 'Resource not found'
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: 'Not Found - Resource does not exist'
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: 'Internal Server Error'
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: 'Internal Server Error - Unexpected server error'
+ summary: 'Get a registered end user'
+ tags:
+ - 'End Users'
+ x-speakeasy-name-override: 'get'
+ patch:
+ description: 'Update registration state without changing identity. State changes do not enforce inference access. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ operationId: 'updateEndUser'
+ parameters:
+ - description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ in: 'path'
+ name: 'user'
+ required: true
+ schema:
+ description: 'Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.'
+ example: 'employee_123'
+ maxLength: 256
+ minLength: 1
+ pattern: '^[^\p{Cc}]+$'
+ type: 'string'
+ requestBody:
+ content:
+ application/json:
+ example:
+ is_active: true
+ schema:
+ $ref: '#/components/schemas/UpdateEndUserRequest'
+ required: true
+ responses:
+ '200':
+ content:
+ application/json:
+ example:
+ data:
+ created_at: '2026-09-16T12:00:00Z'
+ is_active: true
+ updated_at: '2026-09-16T12:00:00Z'
+ user: 'employee_123'
+ schema:
+ $ref: '#/components/schemas/EndUserResponse'
+ description: 'The registered end user. No generated public identifier is returned.'
+ '400':
+ content:
+ application/json:
+ example:
+ error:
+ code: 400
+ message: 'Invalid request parameters'
+ schema:
+ $ref: '#/components/schemas/BadRequestResponse'
+ description: 'Bad Request - Invalid request parameters or malformed input'
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: 'Missing Authentication header'
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: 'Unauthorized - Authentication required or invalid credentials'
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: 'Resource not found'
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: 'Not Found - Resource does not exist'
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: 'Internal Server Error'
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: 'Internal Server Error - Unexpected server error'
+ summary: 'Update a registered end user'
+ tags:
+ - 'End Users'
+ x-speakeasy-name-override: 'update'
+ parameters:
+ - $ref: "#/components/parameters/AppIdentifier"
+ - $ref: "#/components/parameters/AppDisplayName"
+ - $ref: "#/components/parameters/AppCategories"
/endpoints/zdr:
get:
operationId: 'listEndpointsZdr'
@@ -52637,6 +53152,8 @@ tags:
name: 'Datasets'
- description: 'Text embedding endpoints'
name: 'Embeddings'
+ - description: 'End Users endpoints'
+ name: 'End Users'
- description: 'Endpoint information'
name: 'Endpoints'
- description: 'Files endpoints'
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index dd3db004..46ee7ada 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -2,8 +2,8 @@ speakeasyVersion: 1.787.0
sources:
OpenRouter API:
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:834803ef63cfc97ba41255da616c1bc9711490eeba3f2ebfab565090031bdaad
- sourceBlobDigest: sha256:7c20345ae48391f9c96dba9535545e59b6b2ebbb979dab7fd57912cc63ce884a
+ sourceRevisionDigest: sha256:7bc4aac2a9068c7b46e8cf5f90fb4994ef4fcae205748bbd34114c8f9713822c
+ sourceBlobDigest: sha256:d01919a75486dedd849036c7413ff8b451687727058e5bf1985d16f536ad5f86
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:834803ef63cfc97ba41255da616c1bc9711490eeba3f2ebfab565090031bdaad
- sourceBlobDigest: sha256:7c20345ae48391f9c96dba9535545e59b6b2ebbb979dab7fd57912cc63ce884a
+ sourceRevisionDigest: sha256:7bc4aac2a9068c7b46e8cf5f90fb4994ef4fcae205748bbd34114c8f9713822c
+ sourceBlobDigest: sha256:d01919a75486dedd849036c7413ff8b451687727058e5bf1985d16f536ad5f86
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:8ba988604de91796d7efb008917f27c26d144e13f6128b267066b24a2ab86ab5
+ codeSamplesRevisionDigest: sha256:33b893dfc8f4b52290dfe30db1b8a87d46f0b0804dcdcc80a2dcdc61bd9450ab
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.787.0
diff --git a/RELEASES.md b/RELEASES.md
index 779c2a21..585ffb30 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -2879,4 +2879,14 @@ Based on:
### Generated
- [python v1.3.11] .
### Releases
-- [PyPI v1.3.11] https://pypi.org/project/openrouter/1.3.11 - .
\ No newline at end of file
+- [PyPI v1.3.11] https://pypi.org/project/openrouter/1.3.11 - .
+
+## 2026-09-30 18:06:50
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.3.12] .
+### Releases
+- [PyPI v1.3.12] https://pypi.org/project/openrouter/1.3.12 - .
\ No newline at end of file
diff --git a/docs/components/createenduserrequest.mdx b/docs/components/createenduserrequest.mdx
new file mode 100644
index 00000000..daaedee3
--- /dev/null
+++ b/docs/components/createenduserrequest.mdx
@@ -0,0 +1,9 @@
+---
+title: "CreateEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
\ No newline at end of file
diff --git a/docs/components/enduser.mdx b/docs/components/enduser.mdx
new file mode 100644
index 00000000..33111673
--- /dev/null
+++ b/docs/components/enduser.mdx
@@ -0,0 +1,12 @@
+---
+title: "EndUser"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Registration creation time. | 2026-09-16T12:00:00Z |
+| `is_active` | *bool* | :heavy_check_mark: | Whether this registration is active. Not an inference authorization decision. | true |
+| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Last registration lifecycle update time. | 2026-09-16T12:00:00Z |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
\ No newline at end of file
diff --git a/docs/components/enduserresponse.mdx b/docs/components/enduserresponse.mdx
new file mode 100644
index 00000000..4b605db1
--- /dev/null
+++ b/docs/components/enduserresponse.mdx
@@ -0,0 +1,9 @@
+---
+title: "EndUserResponse"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
+| `data` | [components.EndUser](../components/enduser.mdx) | :heavy_check_mark: | N/A | \{
"created_at": "2026-09-16T12:00:00Z",
"is_active": true,
"updated_at": "2026-09-16T12:00:00Z",
"user": "employee_123"
} |
\ No newline at end of file
diff --git a/docs/components/listendusersresponse.mdx b/docs/components/listendusersresponse.mdx
new file mode 100644
index 00000000..b95cdd81
--- /dev/null
+++ b/docs/components/listendusersresponse.mdx
@@ -0,0 +1,10 @@
+---
+title: "ListEndUsersResponse"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- |
+| `data` | List[[components.EndUser](../components/enduser.mdx)] | :heavy_check_mark: | N/A | |
+| `total_count` | *int* | :heavy_check_mark: | Number of registrations matching the filters before pagination. | 1 |
\ No newline at end of file
diff --git a/docs/components/updateenduserrequest.mdx b/docs/components/updateenduserrequest.mdx
new file mode 100644
index 00000000..72a1c5ad
--- /dev/null
+++ b/docs/components/updateenduserrequest.mdx
@@ -0,0 +1,9 @@
+---
+title: "UpdateEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- |
+| `is_active` | *bool* | :heavy_check_mark: | Registration state only; does not enforce inference access. | true |
\ No newline at end of file
diff --git a/docs/docs.json b/docs/docs.json
index b16f280d..184dd7de 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -24,6 +24,7 @@
"sdks/decisions/README",
"sdks/embeddings/README",
"sdks/endpoints/README",
+ "sdks/endusers/README",
"sdks/files/README",
"sdks/generations/README",
"sdks/guardrails/README",
diff --git a/docs/operations/createenduserglobals.mdx b/docs/operations/createenduserglobals.mdx
new file mode 100644
index 00000000..e420bbbe
--- /dev/null
+++ b/docs/operations/createenduserglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "CreateEndUserGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
|
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
|
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
|
\ No newline at end of file
diff --git a/docs/operations/createenduserrequest.mdx b/docs/operations/createenduserrequest.mdx
new file mode 100644
index 00000000..9448f508
--- /dev/null
+++ b/docs/operations/createenduserrequest.mdx
@@ -0,0 +1,12 @@
+---
+title: "CreateEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `create_end_user_request` | [components.CreateEndUserRequest](../components/createenduserrequest.mdx) | :heavy_check_mark: | N/A | \{
"user": "employee_123"
} |
\ No newline at end of file
diff --git a/docs/operations/deleteenduserglobals.mdx b/docs/operations/deleteenduserglobals.mdx
new file mode 100644
index 00000000..07094eff
--- /dev/null
+++ b/docs/operations/deleteenduserglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "DeleteEndUserGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
|
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
|
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
|
\ No newline at end of file
diff --git a/docs/operations/deleteenduserrequest.mdx b/docs/operations/deleteenduserrequest.mdx
new file mode 100644
index 00000000..ad4cacf7
--- /dev/null
+++ b/docs/operations/deleteenduserrequest.mdx
@@ -0,0 +1,12 @@
+---
+title: "DeleteEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
\ No newline at end of file
diff --git a/docs/operations/getenduserglobals.mdx b/docs/operations/getenduserglobals.mdx
new file mode 100644
index 00000000..9ec66ba1
--- /dev/null
+++ b/docs/operations/getenduserglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "GetEndUserGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
|
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
|
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
|
\ No newline at end of file
diff --git a/docs/operations/getenduserrequest.mdx b/docs/operations/getenduserrequest.mdx
new file mode 100644
index 00000000..501f7d29
--- /dev/null
+++ b/docs/operations/getenduserrequest.mdx
@@ -0,0 +1,12 @@
+---
+title: "GetEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
\ No newline at end of file
diff --git a/docs/operations/listendusersglobals.mdx b/docs/operations/listendusersglobals.mdx
new file mode 100644
index 00000000..3b3fecc1
--- /dev/null
+++ b/docs/operations/listendusersglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "ListEndUsersGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
|
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
|
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
|
\ No newline at end of file
diff --git a/docs/operations/listendusersrequest.mdx b/docs/operations/listendusersrequest.mdx
new file mode 100644
index 00000000..0dd8516d
--- /dev/null
+++ b/docs/operations/listendusersrequest.mdx
@@ -0,0 +1,15 @@
+---
+title: "ListEndUsersRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `offset` | *OptionalNullable[int]* | :heavy_minus_sign: | Number of records to skip for pagination | 0 |
+| `limit` | *Optional[int]* | :heavy_minus_sign: | Maximum number of records to return (max 100) | 50 |
+| `user` | *Optional[str]* | :heavy_minus_sign: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `include_inactive` | *Optional[bool]* | :heavy_minus_sign: | Include deactivated registrations. | false |
\ No newline at end of file
diff --git a/docs/operations/listendusersresponse.mdx b/docs/operations/listendusersresponse.mdx
new file mode 100644
index 00000000..d8ac5262
--- /dev/null
+++ b/docs/operations/listendusersresponse.mdx
@@ -0,0 +1,9 @@
+---
+title: "ListEndUsersResponse"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `result` | [components.ListEndUsersResponse](../components/listendusersresponse.mdx) | :heavy_check_mark: | N/A | \{
"data": [
\{
"created_at": "2026-09-16T12:00:00Z",
"is_active": true,
"updated_at": "2026-09-16T12:00:00Z",
"user": "employee_123"
}
],
"total_count": 1
} |
\ No newline at end of file
diff --git a/docs/operations/updateenduserglobals.mdx b/docs/operations/updateenduserglobals.mdx
new file mode 100644
index 00000000..de504b1c
--- /dev/null
+++ b/docs/operations/updateenduserglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "UpdateEndUserGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
|
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
|
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
|
\ No newline at end of file
diff --git a/docs/operations/updateenduserrequest.mdx b/docs/operations/updateenduserrequest.mdx
new file mode 100644
index 00000000..62ae0d75
--- /dev/null
+++ b/docs/operations/updateenduserrequest.mdx
@@ -0,0 +1,13 @@
+---
+title: "UpdateEndUserRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `update_end_user_request` | [components.UpdateEndUserRequest](../components/updateenduserrequest.mdx) | :heavy_check_mark: | N/A | \{
"is_active": true
} |
\ No newline at end of file
diff --git a/docs/sdks/endusers/README.mdx b/docs/sdks/endusers/README.mdx
new file mode 100644
index 00000000..8f4e8760
--- /dev/null
+++ b/docs/sdks/endusers/README.mdx
@@ -0,0 +1,263 @@
+---
+title: "EndUsers"
+description: "End Users endpoints"
+---
+
+## Overview
+
+End Users endpoints
+
+### Available Operations
+
+* [list](#list) - List registered end users
+* [create](#create) - Register an end user
+* [delete](#delete) - Deactivate a registered end user
+* [get](#get) - Get a registered end user
+* [update](#update) - Update a registered end user
+
+## list
+
+List registrations belonging to the authenticated organization. Inactive registrations are excluded by default. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ res = open_router.end_users.list(offset=0, limit=50, include_inactive=False)
+
+ while res is not None:
+ # Handle items
+
+ res = res.next()
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `offset` | *OptionalNullable[int]* | :heavy_minus_sign: | Number of records to skip for pagination | 0 |
+| `limit` | *Optional[int]* | :heavy_minus_sign: | Maximum number of records to return (max 100) | 50 |
+| `user` | *Optional[str]* | :heavy_minus_sign: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `include_inactive` | *Optional[bool]* | :heavy_minus_sign: | Include deactivated registrations. | false |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Response
+
+**[operations.ListEndUsersResponse](../../operations/listendusersresponse.mdx)**
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.BadRequestResponseError | 400 | application/json |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+
+## create
+
+Register a caller-supplied tracking ID under the authenticated organization. No login account, policy, or credentials are created. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ res = open_router.end_users.create(user="employee_123")
+
+ # Handle response
+ print(res)
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Response
+
+**[components.EndUserResponse](../../components/enduserresponse.mdx)**
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.BadRequestResponseError | 400 | application/json |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.ConflictResponseError | 409 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+
+## delete
+
+Soft-deactivate a registration while retaining its tracking ID. Repeat deactivation succeeds. This does not block inference; reactivate through PATCH. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ open_router.end_users.delete(user="employee_123")
+
+ # Use the SDK ...
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.BadRequestResponseError | 400 | application/json |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+
+## get
+
+Retrieve an active or inactive registration by its URL-encoded, caller-supplied tracking ID. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ res = open_router.end_users.get(user="employee_123")
+
+ # Handle response
+ print(res)
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Response
+
+**[components.EndUserResponse](../../components/enduserresponse.mdx)**
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.BadRequestResponseError | 400 | application/json |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+
+## update
+
+Update registration state without changing identity. State changes do not enforce inference access. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ res = open_router.end_users.update(user="employee_123", is_active=True)
+
+ # Handle response
+ print(res)
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `user` | *str* | :heavy_check_mark: | Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths. | employee_123 |
+| `is_active` | *bool* | :heavy_check_mark: | Registration state only; does not enforce inference access. | true |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Response
+
+**[components.EndUserResponse](../../components/enduserresponse.mdx)**
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.BadRequestResponseError | 400 | application/json |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 71e0d536..6372f844 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.3.11"
+version = "1.3.12"
description = "Official Python Client SDK for OpenRouter."
authors = [{ name = "OpenRouter" },]
readme = "README-PYPI.md"
diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py
index 03bc9a3e..b85f7b32 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "1.3.11"
+__version__: str = "1.3.12"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.914.0"
-__user_agent__: str = "speakeasy-sdk/python 1.3.11 2.914.0 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.3.12 2.914.0 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py
index ada2bdeb..42136dee 100644
--- a/src/openrouter/components/__init__.py
+++ b/src/openrouter/components/__init__.py
@@ -1402,6 +1402,10 @@
CreateBYOKKeyResponse,
CreateBYOKKeyResponseTypedDict,
)
+ from .createenduserrequest import (
+ CreateEndUserRequest,
+ CreateEndUserRequestTypedDict,
+ )
from .createguardrailrequest import (
CreateGuardrailRequest,
CreateGuardrailRequestTypedDict,
@@ -1651,6 +1655,8 @@
from .endpointinfo import EndpointInfo, EndpointInfoTypedDict
from .endpointsmetadata import EndpointsMetadata, EndpointsMetadataTypedDict
from .endpointstatus import EndpointStatus
+ from .enduser import EndUser, EndUserTypedDict
+ from .enduserresponse import EndUserResponse, EndUserResponseTypedDict
from .enumcapability import (
EnumCapability,
EnumCapabilityType,
@@ -2301,6 +2307,10 @@
ListEndpointsResponse,
ListEndpointsResponseTypedDict,
)
+ from .listendusersresponse import (
+ ListEndUsersResponse,
+ ListEndUsersResponseTypedDict,
+ )
from .listguardrailsresponse import (
ListGuardrailsResponse,
ListGuardrailsResponseTypedDict,
@@ -4092,6 +4102,10 @@
UpdateBYOKKeyResponse,
UpdateBYOKKeyResponseTypedDict,
)
+ from .updateenduserrequest import (
+ UpdateEndUserRequest,
+ UpdateEndUserRequestTypedDict,
+ )
from .updateguardrailrequest import (
UpdateGuardrailRequest,
UpdateGuardrailRequestTypedDict,
@@ -5264,6 +5278,8 @@
"CreateBYOKKeyRequestTypedDict",
"CreateBYOKKeyResponse",
"CreateBYOKKeyResponseTypedDict",
+ "CreateEndUserRequest",
+ "CreateEndUserRequestTypedDict",
"CreateGuardrailRequest",
"CreateGuardrailRequestTypedDict",
"CreateGuardrailResponse",
@@ -5433,6 +5449,10 @@
"EmbeddingTypedDict",
"Embeddings",
"EmbeddingsTypedDict",
+ "EndUser",
+ "EndUserResponse",
+ "EndUserResponseTypedDict",
+ "EndUserTypedDict",
"Endpoint",
"EndpointInfo",
"EndpointInfoTypedDict",
@@ -5918,6 +5938,8 @@
"LegendTypedDict",
"ListBYOKKeysResponse",
"ListBYOKKeysResponseTypedDict",
+ "ListEndUsersResponse",
+ "ListEndUsersResponseTypedDict",
"ListEndpointsResponse",
"ListEndpointsResponseTypedDict",
"ListGuardrailsResponse",
@@ -7284,6 +7306,8 @@
"UpdateBYOKKeyRequestTypedDict",
"UpdateBYOKKeyResponse",
"UpdateBYOKKeyResponseTypedDict",
+ "UpdateEndUserRequest",
+ "UpdateEndUserRequestTypedDict",
"UpdateGuardrailRequest",
"UpdateGuardrailRequestTypedDict",
"UpdateGuardrailResponse",
@@ -8420,6 +8444,8 @@
"CreateBYOKKeyRequestTypedDict": ".createbyokkeyrequest",
"CreateBYOKKeyResponse": ".createbyokkeyresponse",
"CreateBYOKKeyResponseTypedDict": ".createbyokkeyresponse",
+ "CreateEndUserRequest": ".createenduserrequest",
+ "CreateEndUserRequestTypedDict": ".createenduserrequest",
"CreateGuardrailRequest": ".createguardrailrequest",
"CreateGuardrailRequestTypedDict": ".createguardrailrequest",
"CreateGuardrailResponse": ".createguardrailresponse",
@@ -8599,6 +8625,10 @@
"EndpointsMetadata": ".endpointsmetadata",
"EndpointsMetadataTypedDict": ".endpointsmetadata",
"EndpointStatus": ".endpointstatus",
+ "EndUser": ".enduser",
+ "EndUserTypedDict": ".enduser",
+ "EndUserResponse": ".enduserresponse",
+ "EndUserResponseTypedDict": ".enduserresponse",
"EnumCapability": ".enumcapability",
"EnumCapabilityType": ".enumcapability",
"EnumCapabilityTypedDict": ".enumcapability",
@@ -9075,6 +9105,8 @@
"ArchitectureTypedDict": ".listendpointsresponse",
"ListEndpointsResponse": ".listendpointsresponse",
"ListEndpointsResponseTypedDict": ".listendpointsresponse",
+ "ListEndUsersResponse": ".listendusersresponse",
+ "ListEndUsersResponseTypedDict": ".listendusersresponse",
"ListGuardrailsResponse": ".listguardrailsresponse",
"ListGuardrailsResponseTypedDict": ".listguardrailsresponse",
"ListKeyAssignmentsResponse": ".listkeyassignmentsresponse",
@@ -10423,6 +10455,8 @@
"UpdateBYOKKeyRequestTypedDict": ".updatebyokkeyrequest",
"UpdateBYOKKeyResponse": ".updatebyokkeyresponse",
"UpdateBYOKKeyResponseTypedDict": ".updatebyokkeyresponse",
+ "UpdateEndUserRequest": ".updateenduserrequest",
+ "UpdateEndUserRequestTypedDict": ".updateenduserrequest",
"UpdateGuardrailRequest": ".updateguardrailrequest",
"UpdateGuardrailRequestTypedDict": ".updateguardrailrequest",
"UpdateGuardrailResponse": ".updateguardrailresponse",
diff --git a/src/openrouter/components/createenduserrequest.py b/src/openrouter/components/createenduserrequest.py
new file mode 100644
index 00000000..25623d5f
--- /dev/null
+++ b/src/openrouter/components/createenduserrequest.py
@@ -0,0 +1,15 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.types import BaseModel
+from typing_extensions import TypedDict
+
+
+class CreateEndUserRequestTypedDict(TypedDict):
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+
+class CreateEndUserRequest(BaseModel):
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
diff --git a/src/openrouter/components/enduser.py b/src/openrouter/components/enduser.py
new file mode 100644
index 00000000..1b20f1bb
--- /dev/null
+++ b/src/openrouter/components/enduser.py
@@ -0,0 +1,31 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from datetime import datetime
+from openrouter.types import BaseModel
+from typing_extensions import TypedDict
+
+
+class EndUserTypedDict(TypedDict):
+ created_at: datetime
+ r"""Registration creation time."""
+ is_active: bool
+ r"""Whether this registration is active. Not an inference authorization decision."""
+ updated_at: datetime
+ r"""Last registration lifecycle update time."""
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+
+class EndUser(BaseModel):
+ created_at: datetime
+ r"""Registration creation time."""
+
+ is_active: bool
+ r"""Whether this registration is active. Not an inference authorization decision."""
+
+ updated_at: datetime
+ r"""Last registration lifecycle update time."""
+
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
diff --git a/src/openrouter/components/enduserresponse.py b/src/openrouter/components/enduserresponse.py
new file mode 100644
index 00000000..04707ad9
--- /dev/null
+++ b/src/openrouter/components/enduserresponse.py
@@ -0,0 +1,14 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .enduser import EndUser, EndUserTypedDict
+from openrouter.types import BaseModel
+from typing_extensions import TypedDict
+
+
+class EndUserResponseTypedDict(TypedDict):
+ data: EndUserTypedDict
+
+
+class EndUserResponse(BaseModel):
+ data: EndUser
diff --git a/src/openrouter/components/listendusersresponse.py b/src/openrouter/components/listendusersresponse.py
new file mode 100644
index 00000000..b2fade2a
--- /dev/null
+++ b/src/openrouter/components/listendusersresponse.py
@@ -0,0 +1,20 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .enduser import EndUser, EndUserTypedDict
+from openrouter.types import BaseModel
+from typing import List
+from typing_extensions import TypedDict
+
+
+class ListEndUsersResponseTypedDict(TypedDict):
+ data: List[EndUserTypedDict]
+ total_count: int
+ r"""Number of registrations matching the filters before pagination."""
+
+
+class ListEndUsersResponse(BaseModel):
+ data: List[EndUser]
+
+ total_count: int
+ r"""Number of registrations matching the filters before pagination."""
diff --git a/src/openrouter/components/updateenduserrequest.py b/src/openrouter/components/updateenduserrequest.py
new file mode 100644
index 00000000..0a8dcb3f
--- /dev/null
+++ b/src/openrouter/components/updateenduserrequest.py
@@ -0,0 +1,15 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.types import BaseModel
+from typing_extensions import TypedDict
+
+
+class UpdateEndUserRequestTypedDict(TypedDict):
+ is_active: bool
+ r"""Registration state only; does not enforce inference access."""
+
+
+class UpdateEndUserRequest(BaseModel):
+ is_active: bool
+ r"""Registration state only; does not enforce inference access."""
diff --git a/src/openrouter/end_users.py b/src/openrouter/end_users.py
new file mode 100644
index 00000000..544e6911
--- /dev/null
+++ b/src/openrouter/end_users.py
@@ -0,0 +1,1485 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from .basesdk import BaseSDK
+from jsonpath import JSONPath
+from openrouter import components, errors, operations, utils
+from openrouter._hooks import HookContext
+from openrouter.types import OptionalNullable, UNSET
+from openrouter.utils import get_security_from_env
+from openrouter.utils.unmarshal_json_response import unmarshal_json_response
+from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union
+
+
+class EndUsers(BaseSDK):
+ r"""End Users endpoints"""
+
+ def list(
+ self,
+ *,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ offset: OptionalNullable[int] = 0,
+ limit: Optional[int] = 50,
+ user: Optional[str] = None,
+ include_inactive: Optional[bool] = False,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> Optional[operations.ListEndUsersResponse]:
+ r"""List registered end users
+
+ List registrations belonging to the authenticated organization. Inactive registrations are excluded by default. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param offset: Number of records to skip for pagination
+ :param limit: Maximum number of records to return (max 100)
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param include_inactive: Include deactivated registrations.
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.ListEndUsersRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=offset,
+ limit=limit,
+ user=user,
+ include_inactive=include_inactive,
+ )
+
+ req = self._build_request(
+ method="GET",
+ path="/end-users",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=False,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.ListEndUsersGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="listEndUsers",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ def next_func() -> Optional[operations.ListEndUsersResponse]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return None
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return None
+ limit_ = request.limit if isinstance(request.limit, int) else 50
+ if len(results[0]) < limit_:
+ return None
+ next_offset = offset + len(results[0])
+
+ return self.list(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=next_offset,
+ limit=limit,
+ user=user,
+ include_inactive=include_inactive,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return operations.ListEndUsersResponse(
+ result=unmarshal_json_response(
+ components.ListEndUsersResponse, http_res
+ ),
+ next=next_func,
+ )
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def list_async(
+ self,
+ *,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ offset: OptionalNullable[int] = 0,
+ limit: Optional[int] = 50,
+ user: Optional[str] = None,
+ include_inactive: Optional[bool] = False,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> Optional[operations.ListEndUsersResponse]:
+ r"""List registered end users
+
+ List registrations belonging to the authenticated organization. Inactive registrations are excluded by default. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param offset: Number of records to skip for pagination
+ :param limit: Maximum number of records to return (max 100)
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param include_inactive: Include deactivated registrations.
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.ListEndUsersRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=offset,
+ limit=limit,
+ user=user,
+ include_inactive=include_inactive,
+ )
+
+ req = self._build_request_async(
+ method="GET",
+ path="/end-users",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=False,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.ListEndUsersGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="listEndUsers",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ def next_func() -> Awaitable[Optional[operations.ListEndUsersResponse]]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ async def empty_result():
+ return None
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return empty_result()
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return empty_result()
+ limit_ = request.limit if isinstance(request.limit, int) else 50
+ if len(results[0]) < limit_:
+ return empty_result()
+ next_offset = offset + len(results[0])
+
+ return self.list_async(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=next_offset,
+ limit=limit,
+ user=user,
+ include_inactive=include_inactive,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return operations.ListEndUsersResponse(
+ result=unmarshal_json_response(
+ components.ListEndUsersResponse, http_res
+ ),
+ next=next_func,
+ )
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ def create(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Register an end user
+
+ Register a caller-supplied tracking ID under the authenticated organization. No login account, policy, or credentials are created. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.CreateEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ create_end_user_request=components.CreateEndUserRequest(
+ user=user,
+ ),
+ )
+
+ req = self._build_request(
+ method="POST",
+ path="/end-users",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=True,
+ request_has_path_params=False,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.CreateEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ get_serialized_body=lambda: utils.serialize_request_body(
+ request.create_end_user_request,
+ False,
+ False,
+ "json",
+ components.CreateEndUserRequest,
+ ),
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="createEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "201", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "409", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.ConflictResponseErrorData, http_res
+ )
+ raise errors.ConflictResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def create_async(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Register an end user
+
+ Register a caller-supplied tracking ID under the authenticated organization. No login account, policy, or credentials are created. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.CreateEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ create_end_user_request=components.CreateEndUserRequest(
+ user=user,
+ ),
+ )
+
+ req = self._build_request_async(
+ method="POST",
+ path="/end-users",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=True,
+ request_has_path_params=False,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.CreateEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ get_serialized_body=lambda: utils.serialize_request_body(
+ request.create_end_user_request,
+ False,
+ False,
+ "json",
+ components.CreateEndUserRequest,
+ ),
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="createEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "201", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "409", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.ConflictResponseErrorData, http_res
+ )
+ raise errors.ConflictResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ def delete(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ):
+ r"""Deactivate a registered end user
+
+ Soft-deactivate a registration while retaining its tracking ID. Repeat deactivation succeeds. This does not block inference; reactivate through PATCH. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.DeleteEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ )
+
+ req = self._build_request(
+ method="DELETE",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.DeleteEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="deleteEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "204", "*"):
+ return
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def delete_async(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ):
+ r"""Deactivate a registered end user
+
+ Soft-deactivate a registration while retaining its tracking ID. Repeat deactivation succeeds. This does not block inference; reactivate through PATCH. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.DeleteEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ )
+
+ req = self._build_request_async(
+ method="DELETE",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.DeleteEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="deleteEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "204", "*"):
+ return
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ def get(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Get a registered end user
+
+ Retrieve an active or inactive registration by its URL-encoded, caller-supplied tracking ID. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.GetEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ )
+
+ req = self._build_request(
+ method="GET",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.GetEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="getEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def get_async(
+ self,
+ *,
+ user: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Get a registered end user
+
+ Retrieve an active or inactive registration by its URL-encoded, caller-supplied tracking ID. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.GetEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ )
+
+ req = self._build_request_async(
+ method="GET",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.GetEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="getEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ def update(
+ self,
+ *,
+ user: str,
+ is_active: bool,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Update a registered end user
+
+ Update registration state without changing identity. State changes do not enforce inference access. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param is_active: Registration state only; does not enforce inference access.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.UpdateEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ update_end_user_request=components.UpdateEndUserRequest(
+ is_active=is_active,
+ ),
+ )
+
+ req = self._build_request(
+ method="PATCH",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=True,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.UpdateEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ get_serialized_body=lambda: utils.serialize_request_body(
+ request.update_end_user_request,
+ False,
+ False,
+ "json",
+ components.UpdateEndUserRequest,
+ ),
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="updateEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def update_async(
+ self,
+ *,
+ user: str,
+ is_active: bool,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> components.EndUserResponse:
+ r"""Update a registered end user
+
+ Update registration state without changing identity. State changes do not enforce inference access. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param user: Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths.
+ :param is_active: Registration state only; does not enforce inference access.
+ :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.UpdateEndUserRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ user=user,
+ update_end_user_request=components.UpdateEndUserRequest(
+ is_active=is_active,
+ ),
+ )
+
+ req = self._build_request_async(
+ method="PATCH",
+ path="/end-users/{user}",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=True,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.UpdateEndUserGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ get_serialized_body=lambda: utils.serialize_request_body(
+ request.update_end_user_request,
+ False,
+ False,
+ "json",
+ components.UpdateEndUserRequest,
+ ),
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="updateEndUser",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["End Users"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return unmarshal_json_response(components.EndUserResponse, http_res)
+ if utils.match_response(http_res, "400", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.BadRequestResponseErrorData, http_res
+ )
+ raise errors.BadRequestResponseError(response_data, http_res)
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py
index ee19e0ca..789d0b82 100644
--- a/src/openrouter/operations/__init__.py
+++ b/src/openrouter/operations/__init__.py
@@ -147,6 +147,12 @@
TypeImageURL,
TypeText,
)
+ from .createenduser import (
+ CreateEndUserGlobals,
+ CreateEndUserGlobalsTypedDict,
+ CreateEndUserRequest,
+ CreateEndUserRequestTypedDict,
+ )
from .createguardrail import (
CreateGuardrailGlobals,
CreateGuardrailGlobalsTypedDict,
@@ -302,6 +308,12 @@
DeleteBYOKKeyRequest,
DeleteBYOKKeyRequestTypedDict,
)
+ from .deleteenduser import (
+ DeleteEndUserGlobals,
+ DeleteEndUserGlobalsTypedDict,
+ DeleteEndUserRequest,
+ DeleteEndUserRequestTypedDict,
+ )
from .deletefile import (
DeleteFileGlobals,
DeleteFileGlobalsTypedDict,
@@ -494,6 +506,12 @@
RateLimit,
RateLimitTypedDict,
)
+ from .getenduser import (
+ GetEndUserGlobals,
+ GetEndUserGlobalsTypedDict,
+ GetEndUserRequest,
+ GetEndUserRequestTypedDict,
+ )
from .getfilemetadata import (
GetFileMetadataGlobals,
GetFileMetadataGlobalsTypedDict,
@@ -722,6 +740,14 @@
ListEndpointsZdrResponse,
ListEndpointsZdrResponseTypedDict,
)
+ from .listendusers import (
+ ListEndUsersGlobals,
+ ListEndUsersGlobalsTypedDict,
+ ListEndUsersRequest,
+ ListEndUsersRequestTypedDict,
+ ListEndUsersResponse,
+ ListEndUsersResponseTypedDict,
+ )
from .listfiles import (
ListFilesGlobals,
ListFilesGlobalsTypedDict,
@@ -1037,6 +1063,12 @@
UpdateBYOKKeyRequest,
UpdateBYOKKeyRequestTypedDict,
)
+ from .updateenduser import (
+ UpdateEndUserGlobals,
+ UpdateEndUserGlobalsTypedDict,
+ UpdateEndUserRequest,
+ UpdateEndUserRequestTypedDict,
+ )
from .updateguardrail import (
UpdateGuardrailGlobals,
UpdateGuardrailGlobalsTypedDict,
@@ -1221,6 +1253,10 @@
"CreateEmbeddingsResponseTypedDict",
"CreateEmbeddingsUsage",
"CreateEmbeddingsUsageTypedDict",
+ "CreateEndUserGlobals",
+ "CreateEndUserGlobalsTypedDict",
+ "CreateEndUserRequest",
+ "CreateEndUserRequestTypedDict",
"CreateGuardrailGlobals",
"CreateGuardrailGlobalsTypedDict",
"CreateGuardrailRequest",
@@ -1327,6 +1363,10 @@
"DeleteBatchGlobalsTypedDict",
"DeleteBatchRequest",
"DeleteBatchRequestTypedDict",
+ "DeleteEndUserGlobals",
+ "DeleteEndUserGlobalsTypedDict",
+ "DeleteEndUserRequest",
+ "DeleteEndUserRequestTypedDict",
"DeleteFileGlobals",
"DeleteFileGlobalsTypedDict",
"DeleteFileRequest",
@@ -1465,6 +1505,10 @@
"GetCurrentKeyRequestTypedDict",
"GetCurrentKeyResponse",
"GetCurrentKeyResponseTypedDict",
+ "GetEndUserGlobals",
+ "GetEndUserGlobalsTypedDict",
+ "GetEndUserRequest",
+ "GetEndUserRequestTypedDict",
"GetFileMetadataGlobals",
"GetFileMetadataGlobalsTypedDict",
"GetFileMetadataRequest",
@@ -1617,6 +1661,12 @@
"ListEmbeddingsModelsRequestTypedDict",
"ListEmbeddingsModelsResponse",
"ListEmbeddingsModelsResponseTypedDict",
+ "ListEndUsersGlobals",
+ "ListEndUsersGlobalsTypedDict",
+ "ListEndUsersRequest",
+ "ListEndUsersRequestTypedDict",
+ "ListEndUsersResponse",
+ "ListEndUsersResponseTypedDict",
"ListEndpointsGlobals",
"ListEndpointsGlobalsTypedDict",
"ListEndpointsRequest",
@@ -1878,6 +1928,10 @@
"UpdateBYOKKeyGlobalsTypedDict",
"UpdateBYOKKeyRequest",
"UpdateBYOKKeyRequestTypedDict",
+ "UpdateEndUserGlobals",
+ "UpdateEndUserGlobalsTypedDict",
+ "UpdateEndUserRequest",
+ "UpdateEndUserRequestTypedDict",
"UpdateGuardrailGlobals",
"UpdateGuardrailGlobalsTypedDict",
"UpdateGuardrailRequest",
@@ -2056,6 +2110,10 @@
"PromptTokensDetailsTypedDict": ".createembeddings",
"TypeImageURL": ".createembeddings",
"TypeText": ".createembeddings",
+ "CreateEndUserGlobals": ".createenduser",
+ "CreateEndUserGlobalsTypedDict": ".createenduser",
+ "CreateEndUserRequest": ".createenduser",
+ "CreateEndUserRequestTypedDict": ".createenduser",
"CreateGuardrailGlobals": ".createguardrail",
"CreateGuardrailGlobalsTypedDict": ".createguardrail",
"CreateGuardrailRequest": ".createguardrail",
@@ -2171,6 +2229,10 @@
"DeleteBYOKKeyGlobalsTypedDict": ".deletebyokkey",
"DeleteBYOKKeyRequest": ".deletebyokkey",
"DeleteBYOKKeyRequestTypedDict": ".deletebyokkey",
+ "DeleteEndUserGlobals": ".deleteenduser",
+ "DeleteEndUserGlobalsTypedDict": ".deleteenduser",
+ "DeleteEndUserRequest": ".deleteenduser",
+ "DeleteEndUserRequestTypedDict": ".deleteenduser",
"DeleteFileGlobals": ".deletefile",
"DeleteFileGlobalsTypedDict": ".deletefile",
"DeleteFileRequest": ".deletefile",
@@ -2315,6 +2377,10 @@
"GetCurrentKeyResponseTypedDict": ".getcurrentkey",
"RateLimit": ".getcurrentkey",
"RateLimitTypedDict": ".getcurrentkey",
+ "GetEndUserGlobals": ".getenduser",
+ "GetEndUserGlobalsTypedDict": ".getenduser",
+ "GetEndUserRequest": ".getenduser",
+ "GetEndUserRequestTypedDict": ".getenduser",
"GetFileMetadataGlobals": ".getfilemetadata",
"GetFileMetadataGlobalsTypedDict": ".getfilemetadata",
"GetFileMetadataRequest": ".getfilemetadata",
@@ -2481,6 +2547,12 @@
"ListEndpointsZdrRequestTypedDict": ".listendpointszdr",
"ListEndpointsZdrResponse": ".listendpointszdr",
"ListEndpointsZdrResponseTypedDict": ".listendpointszdr",
+ "ListEndUsersGlobals": ".listendusers",
+ "ListEndUsersGlobalsTypedDict": ".listendusers",
+ "ListEndUsersRequest": ".listendusers",
+ "ListEndUsersRequestTypedDict": ".listendusers",
+ "ListEndUsersResponse": ".listendusers",
+ "ListEndUsersResponseTypedDict": ".listendusers",
"ListFilesGlobals": ".listfiles",
"ListFilesGlobalsTypedDict": ".listfiles",
"ListFilesRequest": ".listfiles",
@@ -2718,6 +2790,10 @@
"UpdateBYOKKeyGlobalsTypedDict": ".updatebyokkey",
"UpdateBYOKKeyRequest": ".updatebyokkey",
"UpdateBYOKKeyRequestTypedDict": ".updatebyokkey",
+ "UpdateEndUserGlobals": ".updateenduser",
+ "UpdateEndUserGlobalsTypedDict": ".updateenduser",
+ "UpdateEndUserRequest": ".updateenduser",
+ "UpdateEndUserRequestTypedDict": ".updateenduser",
"UpdateGuardrailGlobals": ".updateguardrail",
"UpdateGuardrailGlobalsTypedDict": ".updateguardrail",
"UpdateGuardrailRequest": ".updateguardrail",
diff --git a/src/openrouter/operations/createenduser.py b/src/openrouter/operations/createenduser.py
new file mode 100644
index 00000000..9a40dbfc
--- /dev/null
+++ b/src/openrouter/operations/createenduser.py
@@ -0,0 +1,148 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.components import (
+ createenduserrequest as components_createenduserrequest,
+)
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from openrouter.utils import FieldMetadata, HeaderMetadata, RequestMetadata
+import pydantic
+from pydantic import model_serializer
+from typing import Optional
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class CreateEndUserGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class CreateEndUserGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class CreateEndUserRequestTypedDict(TypedDict):
+ create_end_user_request: (
+ components_createenduserrequest.CreateEndUserRequestTypedDict
+ )
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class CreateEndUserRequest(BaseModel):
+ create_end_user_request: Annotated[
+ components_createenduserrequest.CreateEndUserRequest,
+ FieldMetadata(request=RequestMetadata(media_type="application/json")),
+ ]
+
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/operations/deleteenduser.py b/src/openrouter/operations/deleteenduser.py
new file mode 100644
index 00000000..34d3359a
--- /dev/null
+++ b/src/openrouter/operations/deleteenduser.py
@@ -0,0 +1,144 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from openrouter.utils import FieldMetadata, HeaderMetadata, PathParamMetadata
+import pydantic
+from pydantic import model_serializer
+from typing import Optional
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class DeleteEndUserGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class DeleteEndUserGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class DeleteEndUserRequestTypedDict(TypedDict):
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class DeleteEndUserRequest(BaseModel):
+ user: Annotated[
+ str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
+ ]
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/operations/getenduser.py b/src/openrouter/operations/getenduser.py
new file mode 100644
index 00000000..ec4817b7
--- /dev/null
+++ b/src/openrouter/operations/getenduser.py
@@ -0,0 +1,144 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from openrouter.utils import FieldMetadata, HeaderMetadata, PathParamMetadata
+import pydantic
+from pydantic import model_serializer
+from typing import Optional
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class GetEndUserGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class GetEndUserGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class GetEndUserRequestTypedDict(TypedDict):
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class GetEndUserRequest(BaseModel):
+ user: Annotated[
+ str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
+ ]
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/operations/listendusers.py b/src/openrouter/operations/listendusers.py
new file mode 100644
index 00000000..2997608b
--- /dev/null
+++ b/src/openrouter/operations/listendusers.py
@@ -0,0 +1,202 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.components import (
+ listendusersresponse as components_listendusersresponse,
+)
+from openrouter.types import BaseModel, Nullable, OptionalNullable, UNSET_SENTINEL
+from openrouter.utils import FieldMetadata, HeaderMetadata, QueryParamMetadata
+import pydantic
+from pydantic import model_serializer
+from typing import Awaitable, Callable, Optional, Union
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class ListEndUsersGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class ListEndUsersGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class ListEndUsersRequestTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+ offset: NotRequired[Nullable[int]]
+ r"""Number of records to skip for pagination"""
+ limit: NotRequired[int]
+ r"""Maximum number of records to return (max 100)"""
+ user: NotRequired[str]
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+ include_inactive: NotRequired[bool]
+ r"""Include deactivated registrations."""
+
+
+class ListEndUsersRequest(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ offset: Annotated[
+ OptionalNullable[int],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = 0
+ r"""Number of records to skip for pagination"""
+
+ limit: Annotated[
+ Optional[int],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = 50
+ r"""Maximum number of records to return (max 100)"""
+
+ user: Annotated[
+ Optional[str],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = None
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+ include_inactive: Annotated[
+ Optional[bool],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = False
+ r"""Include deactivated registrations."""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ [
+ "HTTP-Referer",
+ "X-OpenRouter-Title",
+ "X-OpenRouter-Categories",
+ "offset",
+ "limit",
+ "user",
+ "include_inactive",
+ ]
+ )
+ nullable_fields = set(["offset"])
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+ is_nullable_and_explicitly_set = (
+ k in nullable_fields
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
+ )
+
+ if val != UNSET_SENTINEL:
+ if (
+ val is not None
+ or k not in optional_fields
+ or is_nullable_and_explicitly_set
+ ):
+ m[k] = val
+
+ return m
+
+
+class ListEndUsersResponseTypedDict(TypedDict):
+ result: components_listendusersresponse.ListEndUsersResponseTypedDict
+
+
+class ListEndUsersResponse(BaseModel):
+ next: Union[
+ Callable[[], Optional[ListEndUsersResponse]],
+ Callable[[], Awaitable[Optional[ListEndUsersResponse]]],
+ ]
+
+ result: components_listendusersresponse.ListEndUsersResponse
diff --git a/src/openrouter/operations/updateenduser.py b/src/openrouter/operations/updateenduser.py
new file mode 100644
index 00000000..2e0d7cce
--- /dev/null
+++ b/src/openrouter/operations/updateenduser.py
@@ -0,0 +1,160 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.components import (
+ updateenduserrequest as components_updateenduserrequest,
+)
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from openrouter.utils import (
+ FieldMetadata,
+ HeaderMetadata,
+ PathParamMetadata,
+ RequestMetadata,
+)
+import pydantic
+from pydantic import model_serializer
+from typing import Optional
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class UpdateEndUserGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class UpdateEndUserGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class UpdateEndUserRequestTypedDict(TypedDict):
+ user: str
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+ update_end_user_request: (
+ components_updateenduserrequest.UpdateEndUserRequestTypedDict
+ )
+ http_referer: NotRequired[str]
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+ x_open_router_title: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class UpdateEndUserRequest(BaseModel):
+ user: Annotated[
+ str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
+ ]
+ r"""Immutable case-sensitive tracking string supplied as user on inference requests. URL-encode it in resource paths."""
+
+ update_end_user_request: Annotated[
+ components_updateenduserrequest.UpdateEndUserRequest,
+ FieldMetadata(request=RequestMetadata(media_type="application/json")),
+ ]
+
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app identifier should be your app's URL and is used as the primary identifier for rankings.
+ This is used to track API usage per application.
+
+ """
+
+ x_open_router_title: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/sdk.py b/src/openrouter/sdk.py
index 0a110f2c..8d7b90d7 100644
--- a/src/openrouter/sdk.py
+++ b/src/openrouter/sdk.py
@@ -29,6 +29,7 @@
from openrouter.credits import Credits
from openrouter.datasets import Datasets
from openrouter.embeddings import Embeddings
+ from openrouter.end_users import EndUsers
from openrouter.endpoints import Endpoints
from openrouter.files import Files
from openrouter.generations import Generations
@@ -85,6 +86,8 @@ class OpenRouter(BaseSDK):
r"""Public OpenRouter usage datasets. Data returned by these endpoints is licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/): reuse and republish it, including commercially, with attribution to OpenRouter."""
embeddings: "Embeddings"
r"""Text embedding endpoints"""
+ end_users: "EndUsers"
+ r"""End Users endpoints"""
endpoints: "Endpoints"
r"""Endpoint information"""
files: "Files"
@@ -143,6 +146,7 @@ class OpenRouter(BaseSDK):
"credits": ("openrouter.credits", "Credits"),
"datasets": ("openrouter.datasets", "Datasets"),
"embeddings": ("openrouter.embeddings", "Embeddings"),
+ "end_users": ("openrouter.end_users", "EndUsers"),
"endpoints": ("openrouter.endpoints", "Endpoints"),
"files": ("openrouter.files", "Files"),
"generations": ("openrouter.generations", "Generations"),
diff --git a/uv.lock b/uv.lock
index 519369b6..49ff3b94 100644
--- a/uv.lock
+++ b/uv.lock
@@ -213,7 +213,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.3.11"
+version = "1.3.12"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },