quicknode-sdk 0.1.0__cp313-cp313-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1663 @@
1
+ Metadata-Version: 2.4
2
+ Name: quicknode-sdk
3
+ Version: 0.1.0
4
+ Classifier: Intended Audience :: Developers
5
+ Classifier: License :: OSI Approved :: MIT License
6
+ Classifier: Operating System :: POSIX :: Linux
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Programming Language :: Rust
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ License-File: LICENSE
15
+ Summary: Quicknode SDK
16
+ Keywords: quicknode,blockchain,sdk,web3,ethereum,solana
17
+ Author-email: John Mitsch <john@quicknode.com>
18
+ License: MIT
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
21
+ Project-URL: Homepage, https://github.com/quicknode/sdk
22
+ Project-URL: Issues, https://github.com/quicknode/sdk/issues
23
+ Project-URL: Repository, https://github.com/quicknode/sdk
24
+
25
+ # quicknode-sdk (Python)
26
+
27
+ Python bindings for the Quicknode SDK.
28
+
29
+ This is one of four language bindings published from the same Rust core. See the [project README](https://github.com/quicknode/sdk/blob/main/README.md) for the polyglot overview, development setup, and release process.
30
+
31
+ ## Table of Contents
32
+
33
+ - [Installation](#installation)
34
+ - [Quick Start](#quick-start)
35
+ - [Configuration](#configuration)
36
+ - [Platform Support](#platform-support)
37
+ - [API Reference](#api-reference)
38
+ - [Admin Client](#admin-client)
39
+ - [Endpoints](#endpoints)
40
+ - [Endpoint Tags](#endpoint-tags)
41
+ - [Teams](#teams)
42
+ - [Usage](#usage)
43
+ - [Logs](#logs)
44
+ - [Endpoint Security](#endpoint-security)
45
+ - [Security Options](#security-options)
46
+ - [Tokens](#tokens)
47
+ - [Referrers](#referrers)
48
+ - [IPs](#ips)
49
+ - [Domain Masks](#domain-masks)
50
+ - [JWTs](#jwts)
51
+ - [Request Filters](#request-filters)
52
+ - [Multichain](#multichain)
53
+ - [IP Custom Headers](#ip-custom-headers)
54
+ - [Method Rate Limits](#method-rate-limits)
55
+ - [Endpoint Rate Limits](#endpoint-rate-limits)
56
+ - [Endpoint URLs](#endpoint-urls)
57
+ - [Metrics](#metrics)
58
+ - [Chains](#chains)
59
+ - [Billing](#billing)
60
+ - [Bulk Operations](#bulk-operations)
61
+ - [Account Tags](#account-tags)
62
+ - [Streams Client](#streams-client)
63
+ - [Datasets, Regions, and Destinations](#datasets-regions-and-destinations)
64
+ - [Streams methods](#streams-methods)
65
+ - [Webhooks Client](#webhooks-client)
66
+ - [Templates and destination](#templates-and-destination)
67
+ - [Webhooks methods](#webhooks-methods)
68
+ - [KV Store Client](#kv-store-client)
69
+ - [Sets](#sets)
70
+ - [Lists](#lists)
71
+ - [Error Handling](#error-handling)
72
+ - [License](#license)
73
+
74
+ ## Installation
75
+
76
+ `uv add quicknode-sdk`
77
+
78
+ ## Quick Start
79
+
80
+ Construct the SDK once, then reach into the four sub-clients (`admin`, `streams`, `webhooks`, `kvstore`). Subsequent API Reference snippets assume you have a `qn` handle from one of these blocks.
81
+
82
+ ```python
83
+ # Python
84
+ import asyncio
85
+ from sdk import QuicknodeSdk
86
+
87
+ async def main():
88
+ qn = QuicknodeSdk.from_env()
89
+ resp = await qn.admin.get_endpoints()
90
+ print(f"{len(resp.data)} endpoints")
91
+
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ ## Configuration
96
+
97
+ There are two ways to configure the SDK.
98
+
99
+ ### Option A — Pass config directly
100
+
101
+ ```python
102
+ # Python
103
+ from sdk import QuicknodeSdk, SdkFullConfig, HttpConfig
104
+ qn = QuicknodeSdk(SdkFullConfig(api_key="your-key", http=HttpConfig(timeout_secs=30)))
105
+ ```
106
+
107
+ ### Option B — Load from environment (`from_env()`)
108
+
109
+ ```python
110
+ # Python
111
+ qn = QuicknodeSdk.from_env()
112
+ ```
113
+
114
+ Environment variables (prefix `QN_SDK__`, separator `__`):
115
+
116
+ | Variable | Required | Default | Description |
117
+ |----------|----------|---------|-------------|
118
+ | `QN_SDK__API_KEY` | yes | — | Your Quicknode API key |
119
+ | `QN_SDK__HTTP__TIMEOUT_SECS` | no | 30 | HTTP request timeout in seconds |
120
+ | `QN_SDK__HTTP__POOL_MAX_IDLE_PER_HOST` | no | — | Max idle HTTP connections per host |
121
+ | `QN_SDK__ADMIN__BASE_URL` | no | `https://api.quicknode.com/v0/` | Override admin API base URL (HTTPS, must end with `/`) |
122
+ | `QN_SDK__STREAMS__BASE_URL` | no | `https://api.quicknode.com/streams/rest/v1/` | Override streams base URL |
123
+ | `QN_SDK__WEBHOOKS__BASE_URL` | no | `https://api.quicknode.com/webhooks/rest/v1/` | Override webhooks base URL |
124
+ | `QN_SDK__KVSTORE__BASE_URL` | no | `https://api.quicknode.com/kv/rest/v1/` | Override KV store base URL |
125
+ | `QN_SDK__HTTP__HEADERS__<NAME>` | no | — | Custom HTTP header sent on every request. Overrides SDK-managed headers (see below). |
126
+
127
+ ### Custom headers and `User-Agent`
128
+
129
+ Every outbound HTTP request includes an auto-generated `User-Agent` of the form:
130
+
131
+ ```
132
+ quicknode-sdk-<language>/<sdk-version> (<os>-<arch>; <language>-<runtime-version>)
133
+ ```
134
+
135
+ You can attach arbitrary headers via `HttpConfig.headers`. **These headers OVERRIDE any SDK-managed header with the same name**, including `User-Agent`, `x-api-key`, `Accept`, and `Content-Type`. Use this to inject correlation IDs, proxy auth, or to replace the default `User-Agent`. Header names are matched case-insensitively.
136
+
137
+ ```python
138
+ from sdk import QuicknodeSdk, SdkFullConfig, HttpConfig
139
+
140
+ qn = QuicknodeSdk(
141
+ SdkFullConfig(
142
+ api_key="your-key",
143
+ http=HttpConfig(headers={
144
+ "X-Correlation-Id": "abc-123",
145
+ "User-Agent": "my-app/1.0", # overrides SDK default
146
+ }),
147
+ )
148
+ )
149
+ ```
150
+
151
+ ## Platform Support
152
+
153
+ Precompiled wheels are published for:
154
+
155
+ | Platform | Targets |
156
+ |---|---|
157
+ | Linux (glibc) | `x86_64`, `aarch64` — glibc **2.17+** (manylinux2014) |
158
+ | Linux (musl) | `x86_64`, `aarch64` — Alpine and other musl distros |
159
+ | macOS | Apple Silicon (`arm64`) |
160
+
161
+ Linux glibc wheels are built against glibc 2.17 so they load on any distro from 2014 onward — RHEL 7+, Ubuntu 14.04+, Debian 8+, Amazon Linux 2+, SLES 12+, Fedora 19+. If `pip install quicknode-sdk` resolves to a source distribution on your platform, you're on something we don't have a prebuilt wheel for — see the matrix above.
162
+
163
+ **Not supported:** RHEL/CentOS 6 (glibc 2.12), Debian 7 (glibc 2.13), Ubuntu 12.04 (glibc 2.15), SLES 11 (glibc 2.11), Intel macOS, Windows.
164
+
165
+ ## API Reference
166
+
167
+ Snippets assume `qn` was already constructed via the Quick Start. Optional parameters are skipped unless showing one is needed to illustrate usage.
168
+
169
+ ### Language conventions
170
+
171
+ - Methods are `async` — call with `await`. Parameters are kwargs; responses are native `pyclass` objects with attribute access.
172
+
173
+ ---
174
+
175
+ ### Admin Client
176
+
177
+ Accessed as `qn.admin`. Manages endpoints, tags, teams, billing, usage, metrics, security, and rate limits. Backed by `https://api.quicknode.com/v0/`.
178
+
179
+ #### Endpoints
180
+
181
+ ##### `get_endpoints` / `getEndpoints`
182
+
183
+ Returns a paginated list of endpoints on the account with optional search, filters (networks, statuses, labels, tags, dedicated, flat-rate), sorting, and pagination.
184
+
185
+ **Parameters** (all optional): `limit` (i32), `offset` (i32), `search` (string), `sort_by` (string), `sort_direction` (`"asc"` | `"desc"`), `networks` (string[]), `statuses` (string[]), `labels` (string[]), `dedicated` (bool), `is_flat_rate` (bool), `tag_ids` (i32[]), `tag_labels` (string[]).
186
+
187
+ **Returns**: `GetEndpointsResponse` — `{ data: Endpoint[], pagination?: Pagination }`.
188
+
189
+ ```python
190
+ # Python
191
+ resp = await qn.admin.get_endpoints(limit=20, sort_by="created_at", sort_direction="desc")
192
+ ```
193
+
194
+ ##### `create_endpoint` / `createEndpoint`
195
+
196
+ Creates a new endpoint for the given blockchain and network.
197
+
198
+ **Parameters**: `chain` (string, optional), `network` (string, optional).
199
+
200
+ **Returns**: `CreateEndpointResponse` with `data: SingleEndpoint`.
201
+
202
+ ```python
203
+ # Python
204
+ resp = await qn.admin.create_endpoint(chain="ethereum", network="mainnet")
205
+ ```
206
+
207
+ ##### `show_endpoint` / `showEndpoint`
208
+
209
+ Fetches a single endpoint by id, including its full security configuration and rate limits.
210
+
211
+ **Parameters**: `id` (string, required).
212
+
213
+ **Returns**: `ShowEndpointResponse` with `data: SingleEndpoint`.
214
+
215
+ ```python
216
+ # Python
217
+ resp = await qn.admin.show_endpoint("ep-123")
218
+ ```
219
+
220
+ ##### `update_endpoint` / `updateEndpoint`
221
+
222
+ Updates editable fields on an endpoint. Currently supports `label`.
223
+
224
+ **Parameters**: `id` (string, required); body: `label` (string, optional).
225
+
226
+ **Returns**: nothing.
227
+
228
+ ```python
229
+ # Python
230
+ await qn.admin.update_endpoint("ep-123", label="my label")
231
+ ```
232
+
233
+ ##### `archive_endpoint` / `archiveEndpoint`
234
+
235
+ Archives an endpoint. The HTTP verb is `DELETE` but the effect is archival, not permanent deletion.
236
+
237
+ **Parameters**: `id` (string, required).
238
+
239
+ **Returns**: nothing.
240
+
241
+ ```python
242
+ # Python
243
+ await qn.admin.archive_endpoint("ep-123")
244
+ ```
245
+
246
+ ##### `update_endpoint_status` / `updateEndpointStatus`
247
+
248
+ Pauses or unpauses an endpoint.
249
+
250
+ **Parameters**: `id` (string, required); body: `status` (string, required — `"active"` or `"paused"`).
251
+
252
+ **Returns**: `UpdateEndpointStatusResponse`.
253
+
254
+ ```python
255
+ # Python
256
+ await qn.admin.update_endpoint_status("ep-123", status="paused")
257
+ ```
258
+
259
+ #### Endpoint Tags
260
+
261
+ Per-endpoint tag add/remove. For account-wide tag management see [Account Tags](#account-tags).
262
+
263
+ ##### `create_tag` / `createTag`
264
+
265
+ Tags an endpoint with the given label. Creates the tag on the account if it does not exist.
266
+
267
+ **Parameters**: `id` (string, required); body: `label` (string, optional).
268
+
269
+ **Returns**: nothing.
270
+
271
+ ```python
272
+ # Python
273
+ await qn.admin.create_tag("ep-123", label="prod")
274
+ ```
275
+
276
+ ##### `delete_tag` / `deleteTag`
277
+
278
+ Removes a tag from a specific endpoint.
279
+
280
+ **Parameters**: `id` (endpoint id, string, required), `tag_id` (string, required).
281
+
282
+ **Returns**: nothing.
283
+
284
+ ```python
285
+ # Python
286
+ await qn.admin.delete_tag("ep-123", "42")
287
+ ```
288
+
289
+ #### Teams
290
+
291
+ ##### `list_teams` / `listTeams`
292
+
293
+ Lists all teams on the account.
294
+
295
+ **Parameters**: none.
296
+
297
+ **Returns**: `ListTeamsResponse` with `data: TeamSummary[]`.
298
+
299
+ ```python
300
+ # Python
301
+ resp = await qn.admin.list_teams()
302
+ ```
303
+
304
+ ##### `create_team` / `createTeam`
305
+
306
+ Creates a new team.
307
+
308
+ **Parameters**: `name` (string, required).
309
+
310
+ **Returns**: `CreateTeamResponse` with `data: CreateTeamData`.
311
+
312
+ ```python
313
+ # Python
314
+ resp = await qn.admin.create_team(name="Payments")
315
+ ```
316
+
317
+ ##### `get_team` / `getTeam`
318
+
319
+ Fetches team detail including pending invites.
320
+
321
+ **Parameters**: `id` (i64, required).
322
+
323
+ **Returns**: `GetTeamResponse` with `data: TeamDetail`.
324
+
325
+ ```python
326
+ # Python
327
+ resp = await qn.admin.get_team(42)
328
+ ```
329
+
330
+ ##### `delete_team` / `deleteTeam`
331
+
332
+ Deletes a team.
333
+
334
+ **Parameters**: `id` (i64, required).
335
+
336
+ **Returns**: `DeleteTeamResponse`.
337
+
338
+ ```python
339
+ # Python
340
+ await qn.admin.delete_team(42)
341
+ ```
342
+
343
+ ##### `list_team_endpoints` / `listTeamEndpoints`
344
+
345
+ Lists endpoints accessible to a team.
346
+
347
+ **Parameters**: `id` (i64, required).
348
+
349
+ **Returns**: `ListTeamEndpointsResponse` with `data: TeamEndpoint[]`.
350
+
351
+ ```python
352
+ # Python
353
+ resp = await qn.admin.list_team_endpoints(42)
354
+ ```
355
+
356
+ ##### `update_team_endpoints` / `updateTeamEndpoints`
357
+
358
+ Replaces the set of endpoints associated with a team. Pass an empty array to remove all.
359
+
360
+ **Parameters**: `id` (i64, required); body: `endpoint_ids` (string[], required).
361
+
362
+ **Returns**: `UpdateTeamEndpointsResponse`.
363
+
364
+ ```python
365
+ # Python
366
+ await qn.admin.update_team_endpoints(42, endpoint_ids=["ep-123", "ep-456"])
367
+ ```
368
+
369
+ ##### `invite_team_member` / `inviteTeamMember`
370
+
371
+ Invites a user to a team. Existing users only need `email`; new users require `full_name` and `role`.
372
+
373
+ **Parameters**: `id` (i64, required); body: `email` (string, required), `full_name` (string, optional), `role` (string, optional — `admin` | `viewer` | `billing`).
374
+
375
+ **Returns**: `InviteTeamMemberResponse`.
376
+
377
+ ```python
378
+ # Python
379
+ await qn.admin.invite_team_member(42, email="alice@example.com", role="viewer")
380
+ ```
381
+
382
+ ##### `remove_team_member` / `removeTeamMember`
383
+
384
+ Removes a user from a team.
385
+
386
+ **Parameters**: `id` (team id, i64, required), `user_id` (i64, required).
387
+
388
+ **Returns**: `RemoveTeamMemberResponse`.
389
+
390
+ ```python
391
+ # Python
392
+ await qn.admin.remove_team_member(42, 7)
393
+ ```
394
+
395
+ ##### `resend_team_invite` / `resendTeamInvite`
396
+
397
+ Re-sends a pending team invitation.
398
+
399
+ **Parameters**: `id` (team id, i64, required), `user_id` (i64, required).
400
+
401
+ **Returns**: `ResendTeamInviteResponse`.
402
+
403
+ ```python
404
+ # Python
405
+ await qn.admin.resend_team_invite(42, 7)
406
+ ```
407
+
408
+ #### Usage
409
+
410
+ All usage methods accept optional `start_time` and `end_time` Unix timestamps. Omit both for account-to-date totals.
411
+
412
+ ##### `get_usage` / `getUsage`
413
+
414
+ Aggregate account usage for a time window.
415
+
416
+ **Returns**: `GetUsageResponse` with `data: UsageData` (`credits_used`, `credits_remaining`, `limit`, `overages`, `start_time`, `end_time`).
417
+
418
+ ```python
419
+ # Python
420
+ resp = await qn.admin.get_usage()
421
+ ```
422
+
423
+ ##### `get_usage_by_endpoint` / `getUsageByEndpoint`
424
+
425
+ Per-endpoint usage breakdown.
426
+
427
+ **Returns**: `GetUsageByEndpointResponse` with `data.endpoints: EndpointUsage[]`.
428
+
429
+ ```python
430
+ # Python
431
+ resp = await qn.admin.get_usage_by_endpoint()
432
+ ```
433
+
434
+ ##### `get_usage_by_method` / `getUsageByMethod`
435
+
436
+ Per-RPC-method usage breakdown.
437
+
438
+ **Returns**: `GetUsageByMethodResponse` with `data.methods: MethodUsage[]`.
439
+
440
+ ```python
441
+ # Python
442
+ resp = await qn.admin.get_usage_by_method()
443
+ ```
444
+
445
+ ##### `get_usage_by_chain` / `getUsageByChain`
446
+
447
+ Per-chain usage breakdown.
448
+
449
+ **Returns**: `GetUsageByChainResponse` with `data.chains: ChainUsage[]`.
450
+
451
+ ```python
452
+ # Python
453
+ resp = await qn.admin.get_usage_by_chain()
454
+ ```
455
+
456
+ ##### `get_usage_by_tag` / `getUsageByTag`
457
+
458
+ Per-tag usage breakdown.
459
+
460
+ **Returns**: `GetUsageByTagResponse` with `data.tags: TagUsage[]`.
461
+
462
+ ```python
463
+ # Python
464
+ resp = await qn.admin.get_usage_by_tag()
465
+ ```
466
+
467
+ #### Logs
468
+
469
+ ##### `get_endpoint_logs` / `getEndpointLogs`
470
+
471
+ Fetches a page of request logs for an endpoint. Set `include_details=true` for full request/response payloads (truncated at 2 KB each).
472
+
473
+ **Parameters**: `id` (endpoint id, required); body: `from` (string timestamp, required), `to` (string timestamp, required), `include_details` (bool, optional), `limit` (i32, optional), `next_at` (string cursor, optional).
474
+
475
+ **Returns**: `GetEndpointLogsResponse` — `{ data: EndpointLog[], next_at?: string }`.
476
+
477
+ ```python
478
+ # Python
479
+ resp = await qn.admin.get_endpoint_logs(
480
+ "ep-123",
481
+ from_time="2026-04-01T00:00:00Z",
482
+ to_time="2026-04-02T00:00:00Z",
483
+ limit=100,
484
+ )
485
+ ```
486
+
487
+ ##### `get_log_details` / `getLogDetails`
488
+
489
+ Returns the full request/response payloads for a single log entry.
490
+
491
+ **Parameters**: `id` (endpoint id, required), `request_id` (log request uuid, required).
492
+
493
+ **Returns**: `GetLogDetailsResponse` with `data: LogDetails`.
494
+
495
+ ```python
496
+ # Python
497
+ resp = await qn.admin.get_log_details("ep-123", "req-abc")
498
+ ```
499
+
500
+ #### Endpoint Security
501
+
502
+ ##### `get_endpoint_security` / `getEndpointSecurity`
503
+
504
+ Returns the full security configuration for an endpoint: tokens, JWTs, referrers, domain masks, IPs, request filters, and their per-feature toggles.
505
+
506
+ **Parameters**: `id` (string, required).
507
+
508
+ **Returns**: `GetEndpointSecurityResponse` with `data: EndpointSecurity`.
509
+
510
+ ```python
511
+ # Python
512
+ resp = await qn.admin.get_endpoint_security("ep-123")
513
+ ```
514
+
515
+ #### Security Options
516
+
517
+ ##### `get_security_options` / `getSecurityOptions`
518
+
519
+ Returns the list of security features and their enabled state for an endpoint.
520
+
521
+ **Parameters**: `id` (string, required).
522
+
523
+ **Returns**: `GetSecurityOptionsResponse` with `data: SecurityOption[]`.
524
+
525
+ ```python
526
+ # Python
527
+ resp = await qn.admin.get_security_options("ep-123")
528
+ ```
529
+
530
+ ##### `update_security_options` / `updateSecurityOptions`
531
+
532
+ Enables or disables individual security features. Each field accepts `"enabled"` or `"disabled"`.
533
+
534
+ **Parameters**: `id` (string, required); `options`: `SecurityOptionsUpdate` (`tokens`, `referrers`, `jwts`, `ips`, `domain_masks`, `hsts`, `cors`, `request_filters`, `ip_custom_header`).
535
+
536
+ **Returns**: `UpdateSecurityOptionsResponse` with updated `SecurityOption[]`.
537
+
538
+ ```python
539
+ # Python
540
+ await qn.admin.update_security_options(
541
+ "ep-123",
542
+ tokens="enabled",
543
+ jwts="disabled",
544
+ )
545
+ ```
546
+
547
+ #### Tokens
548
+
549
+ ##### `create_token` / `createToken`
550
+
551
+ Generates a new auth token on an endpoint.
552
+
553
+ **Parameters**: `id` (endpoint id, required).
554
+
555
+ **Returns**: nothing.
556
+
557
+ ```python
558
+ # Python
559
+ await qn.admin.create_token("ep-123")
560
+ ```
561
+
562
+ ##### `delete_token` / `deleteToken`
563
+
564
+ Revokes a token on an endpoint.
565
+
566
+ **Parameters**: `id` (endpoint id, required), `token_id` (string, required).
567
+
568
+ **Returns**: nothing.
569
+
570
+ ```python
571
+ # Python
572
+ await qn.admin.delete_token("ep-123", "tok-1")
573
+ ```
574
+
575
+ #### Referrers
576
+
577
+ ##### `create_referrer` / `createReferrer`
578
+
579
+ Whitelists a referrer URL or domain on an endpoint.
580
+
581
+ **Parameters**: `id` (endpoint id, required); body: `referrer` (string, optional).
582
+
583
+ **Returns**: nothing.
584
+
585
+ ```python
586
+ # Python
587
+ await qn.admin.create_referrer("ep-123", referrer="example.com")
588
+ ```
589
+
590
+ ##### `delete_referrer` / `deleteReferrer`
591
+
592
+ Removes a referrer from the whitelist.
593
+
594
+ **Parameters**: `id` (endpoint id, required), `referrer_id` (string, required).
595
+
596
+ **Returns**: nothing.
597
+
598
+ ```python
599
+ # Python
600
+ await qn.admin.delete_referrer("ep-123", "ref-1")
601
+ ```
602
+
603
+ #### IPs
604
+
605
+ ##### `create_ip` / `createIp`
606
+
607
+ Whitelists an IP address on an endpoint.
608
+
609
+ **Parameters**: `id` (endpoint id, required); body: `ip` (string, optional).
610
+
611
+ **Returns**: nothing.
612
+
613
+ ```python
614
+ # Python
615
+ await qn.admin.create_ip("ep-123", ip="198.51.100.7")
616
+ ```
617
+
618
+ ##### `delete_ip` / `deleteIp`
619
+
620
+ Removes an IP from the whitelist.
621
+
622
+ **Parameters**: `id` (endpoint id, required), `ip_id` (string, required).
623
+
624
+ **Returns**: `DeleteBoolResponse`.
625
+
626
+ ```python
627
+ # Python
628
+ await qn.admin.delete_ip("ep-123", "ip-1")
629
+ ```
630
+
631
+ #### Domain Masks
632
+
633
+ ##### `create_domain_mask` / `createDomainMask`
634
+
635
+ Adds a custom domain mask to an endpoint.
636
+
637
+ **Parameters**: `id` (endpoint id, required); body: `domain_mask` (string, optional).
638
+
639
+ **Returns**: nothing.
640
+
641
+ ```python
642
+ # Python
643
+ await qn.admin.create_domain_mask("ep-123", domain_mask="rpc.example.com")
644
+ ```
645
+
646
+ ##### `delete_domain_mask` / `deleteDomainMask`
647
+
648
+ Removes a domain mask.
649
+
650
+ **Parameters**: `id` (endpoint id, required), `domain_mask_id` (string, required).
651
+
652
+ **Returns**: nothing.
653
+
654
+ ```python
655
+ # Python
656
+ await qn.admin.delete_domain_mask("ep-123", "dm-1")
657
+ ```
658
+
659
+ #### JWTs
660
+
661
+ ##### `create_jwt` / `createJwt`
662
+
663
+ Configures JWT validation on an endpoint.
664
+
665
+ **Parameters**: `id` (endpoint id, required); body: `public_key` (string, optional), `kid` (string, optional), `name` (string, optional).
666
+
667
+ **Returns**: nothing.
668
+
669
+ ```python
670
+ # Python
671
+ await qn.admin.create_jwt(
672
+ "ep-123",
673
+ public_key="-----BEGIN PUBLIC KEY-----\n...",
674
+ kid="key-1",
675
+ name="primary",
676
+ )
677
+ ```
678
+
679
+ ##### `delete_jwt` / `deleteJwt`
680
+
681
+ Removes a JWT configuration.
682
+
683
+ **Parameters**: `id` (endpoint id, required), `jwt_id` (string, required).
684
+
685
+ **Returns**: nothing.
686
+
687
+ ```python
688
+ # Python
689
+ await qn.admin.delete_jwt("ep-123", "jwt-1")
690
+ ```
691
+
692
+ #### Request Filters
693
+
694
+ Whitelist specific RPC methods on an endpoint. Requests for methods not on the list are blocked when the feature is enabled.
695
+
696
+ ##### `create_request_filter` / `createRequestFilter`
697
+
698
+ **Parameters**: `id` (endpoint id, required); body: `method` (string[], optional). Ruby's Hash key is `methods` (plural).
699
+
700
+ **Returns**: `CreateRequestFilterResponse` with `data.id`.
701
+
702
+ ```python
703
+ # Python
704
+ resp = await qn.admin.create_request_filter(
705
+ "ep-123",
706
+ method=["eth_blockNumber", "eth_getBalance"],
707
+ )
708
+ ```
709
+
710
+ ##### `update_request_filter` / `updateRequestFilter`
711
+
712
+ **Parameters**: `id` (endpoint id, required), `request_filter_id` (string, required); body: `method` (string[], optional). Ruby's Hash keys are `request_filter_id` and `methods` (plural).
713
+
714
+ **Returns**: nothing.
715
+
716
+ ```python
717
+ # Python
718
+ await qn.admin.update_request_filter("ep-123", "f-1", method=["eth_call"])
719
+ ```
720
+
721
+ ##### `delete_request_filter` / `deleteRequestFilter`
722
+
723
+ **Parameters**: `id` (endpoint id, required), `request_filter_id` (string, required).
724
+
725
+ **Returns**: nothing.
726
+
727
+ ```python
728
+ # Python
729
+ await qn.admin.delete_request_filter("ep-123", "f-1")
730
+ ```
731
+
732
+ #### Multichain
733
+
734
+ ##### `enable_multichain` / `enableMultichain`
735
+
736
+ Enables multichain on an endpoint.
737
+
738
+ **Parameters**: `id` (endpoint id, required).
739
+
740
+ **Returns**: nothing.
741
+
742
+ ```python
743
+ # Python
744
+ await qn.admin.enable_multichain("ep-123")
745
+ ```
746
+
747
+ ##### `disable_multichain` / `disableMultichain`
748
+
749
+ Disables multichain on an endpoint.
750
+
751
+ **Parameters**: `id` (endpoint id, required).
752
+
753
+ **Returns**: nothing.
754
+
755
+ ```python
756
+ # Python
757
+ await qn.admin.disable_multichain("ep-123")
758
+ ```
759
+
760
+ #### IP Custom Headers
761
+
762
+ ##### `create_or_update_ip_custom_header` / `createOrUpdateIpCustomHeader`
763
+
764
+ Sets the custom header used to identify the client IP (e.g. when traffic is proxied).
765
+
766
+ **Parameters**: `id` (endpoint id, required); body: `header_name` (string, required).
767
+
768
+ **Returns**: `CreateOrUpdateIpCustomHeaderResponse` with `data.header_name`.
769
+
770
+ ```python
771
+ # Python
772
+ await qn.admin.create_or_update_ip_custom_header("ep-123", header_name="X-Forwarded-For")
773
+ ```
774
+
775
+ ##### `delete_ip_custom_header` / `deleteIpCustomHeader`
776
+
777
+ Removes the custom IP header configuration.
778
+
779
+ **Parameters**: `id` (endpoint id, required).
780
+
781
+ **Returns**: `DeleteBoolResponse`.
782
+
783
+ ```python
784
+ # Python
785
+ await qn.admin.delete_ip_custom_header("ep-123")
786
+ ```
787
+
788
+ #### Method Rate Limits
789
+
790
+ ##### `get_method_rate_limits` / `getMethodRateLimits`
791
+
792
+ Lists method-level rate limiters configured on an endpoint.
793
+
794
+ **Parameters**: `id` (endpoint id, required).
795
+
796
+ **Returns**: `GetMethodRateLimitsResponse` with `data.rate_limiters: MethodRateLimiter[]`.
797
+
798
+ ```python
799
+ # Python
800
+ resp = await qn.admin.get_method_rate_limits("ep-123")
801
+ ```
802
+
803
+ ##### `create_method_rate_limit` / `createMethodRateLimit`
804
+
805
+ Creates a new method-level rate limiter.
806
+
807
+ **Parameters**: `id` (endpoint id, required); body: `interval` (string, e.g. `"second"`), `methods` (string[]), `rate` (i32).
808
+
809
+ **Returns**: `CreateMethodRateLimitResponse` with `data: MethodRateLimiter`.
810
+
811
+ ```python
812
+ # Python
813
+ resp = await qn.admin.create_method_rate_limit(
814
+ "ep-123",
815
+ interval="second",
816
+ methods=["eth_call"],
817
+ rate=10,
818
+ )
819
+ ```
820
+
821
+ ##### `update_method_rate_limit` / `updateMethodRateLimit`
822
+
823
+ Updates an existing rate limiter. Only provided fields change.
824
+
825
+ **Parameters**: `id` (endpoint id, required), `method_rate_limit_id` (string, required); body: `methods` (string[], optional), `status` (`"enabled"` | `"disabled"`, optional), `rate` (i32, optional).
826
+
827
+ **Returns**: `UpdateMethodRateLimitResponse`.
828
+
829
+ ```python
830
+ # Python
831
+ await qn.admin.update_method_rate_limit("ep-123", "rl-1", rate=50)
832
+ ```
833
+
834
+ ##### `delete_method_rate_limit` / `deleteMethodRateLimit`
835
+
836
+ Deletes a rate limiter.
837
+
838
+ **Parameters**: `id` (endpoint id, required), `method_rate_limit_id` (string, required).
839
+
840
+ **Returns**: nothing.
841
+
842
+ ```python
843
+ # Python
844
+ await qn.admin.delete_method_rate_limit("ep-123", "rl-1")
845
+ ```
846
+
847
+ #### Endpoint Rate Limits
848
+
849
+ ##### `update_rate_limits` / `updateRateLimits`
850
+
851
+ Partial update of the endpoint-level RPS / RPM / RPD caps. Only buckets included in the request are modified — omitted buckets are left unchanged. Values are capped by the account's plan tier. Sends `PATCH`.
852
+
853
+ **Parameters**: `id` (endpoint id, required); `rate_limits`: `RateLimitSettings` (`rps`, `rpm`, `rpd`, all optional).
854
+
855
+ **Returns**: nothing.
856
+
857
+ ```python
858
+ # Python
859
+ await qn.admin.update_rate_limits("ep-123", rps=100, rpm=5000)
860
+ ```
861
+
862
+ ##### `get_rate_limits` / `getRateLimits`
863
+
864
+ Returns the rate-limit rows currently enforced on the endpoint, each identifying its `bucket` (`"rps"` / `"rpm"` / `"rpd"`), `rate_limit`, and `source` (`"plan_default"` or `"user_override"`). User-set overrides expose an `id` (camelCased `id` in Node) you can pass to `delete_rate_limit_override`.
865
+
866
+ **Parameters**: `id` (endpoint id, required).
867
+
868
+ **Returns**: `GetRateLimitsResponse` with `data.rate_limits: RateLimitEntry[]`.
869
+
870
+ ```python
871
+ # Python
872
+ resp = await qn.admin.get_rate_limits("123")
873
+ for row in resp.data.rate_limits:
874
+ print(row.bucket, row.rate_limit, row.source, row.id)
875
+ ```
876
+
877
+ ##### `delete_rate_limit_override` / `deleteRateLimitOverride`
878
+
879
+ Deletes a user-set rate-limit override by UUID. Plan defaults are not deletable — passing a UUID that does not match a user-set override on the endpoint returns 404.
880
+
881
+ **Parameters**: `id` (endpoint id, required); `override_id` / `overrideId` (UUID returned by `get_rate_limits`, required).
882
+
883
+ **Returns**: nothing.
884
+
885
+ ```python
886
+ # Python
887
+ await qn.admin.delete_rate_limit_override("123", "ovr-uuid")
888
+ ```
889
+
890
+ #### Endpoint URLs
891
+
892
+ ##### `get_endpoint_urls` / `getEndpointUrls`
893
+
894
+ Returns the HTTP and WebSocket URLs for the endpoint without fetching the full endpoint record. For multichain endpoints, `multichain_urls` / `multichainUrls` is a per-network map of additional URLs; for single-chain endpoints it is `None` / `null`.
895
+
896
+ **Parameters**: `id` (endpoint id, required).
897
+
898
+ **Returns**: `GetEndpointUrlsResponse` with `data.http_url`, `data.wss_url`, and `data.multichain_urls`.
899
+
900
+ ```python
901
+ # Python
902
+ resp = await qn.admin.get_endpoint_urls("123")
903
+ print(resp.data.http_url)
904
+ if resp.data.multichain_urls:
905
+ for network, urls in resp.data.multichain_urls.items():
906
+ print(network, urls.http_url)
907
+ ```
908
+
909
+ #### Metrics
910
+
911
+ ##### `get_endpoint_metrics` / `getEndpointMetrics`
912
+
913
+ Returns metric series for an endpoint over a time period.
914
+
915
+ **Parameters**: `id` (endpoint id, required); body: `period` (`"hour"` | `"day"` | `"week"` | `"month"`), `metric` (e.g. `"method_calls_over_time"`, `"response_status_breakdown"`).
916
+
917
+ **Returns**: `GetEndpointMetricsResponse` with `data: list[EndpointMetric]`. Each `EndpointMetric` has a `tag: list[str]` and a `data: list[list[int]]` of `[timestamp, value]` pairs. Single-axis series (e.g. `response_time_over_time` with a percentile) come back as a one-element tag like `["p95"]`; multi-axis series come back as `["network", "arbitrum-mainnet"]`.
918
+
919
+ ```python
920
+ # Python
921
+ resp = await qn.admin.get_endpoint_metrics(
922
+ "ep-123",
923
+ period="day",
924
+ metric="method_calls_over_time",
925
+ )
926
+ ```
927
+
928
+ ##### `get_account_metrics` / `getAccountMetrics`
929
+
930
+ Returns account-level metric series. Supports an optional `percentile` (e.g. `"p50"`, `"p95"`, `"p99"`) for latency metrics.
931
+
932
+ **Parameters**: `period` (required), `metric` (required), `percentile` (string, optional).
933
+
934
+ **Returns**: `GetAccountMetricsResponse` with `data: list[EndpointMetric]`. See `get_endpoint_metrics` above for the `tag: list[str]` shape.
935
+
936
+ ```python
937
+ # Python
938
+ resp = await qn.admin.get_account_metrics(period="day", metric="credits_over_time")
939
+ ```
940
+
941
+ #### Chains
942
+
943
+ ##### `list_chains` / `listChains`
944
+
945
+ Lists the blockchains supported by Quicknode along with their networks.
946
+
947
+ **Parameters**: none.
948
+
949
+ **Returns**: `ListChainsResponse` with `data: Chain[]`.
950
+
951
+ ```python
952
+ # Python
953
+ resp = await qn.admin.list_chains()
954
+ ```
955
+
956
+ #### Billing
957
+
958
+ ##### `list_invoices` / `listInvoices`
959
+
960
+ Lists invoices on the account.
961
+
962
+ **Parameters**: none.
963
+
964
+ **Returns**: `ListInvoicesResponse` with `data.invoices: Invoice[]`.
965
+
966
+ ```python
967
+ # Python
968
+ resp = await qn.admin.list_invoices()
969
+ ```
970
+
971
+ ##### `list_payments` / `listPayments`
972
+
973
+ Lists payments on the account.
974
+
975
+ **Parameters**: none.
976
+
977
+ **Returns**: `ListPaymentsResponse` with `data.payments: Payment[]`.
978
+
979
+ ```python
980
+ # Python
981
+ resp = await qn.admin.list_payments()
982
+ ```
983
+
984
+ #### Bulk Operations
985
+
986
+ ##### `bulk_update_endpoint_status` / `bulkUpdateEndpointStatus`
987
+
988
+ Activates or pauses many endpoints at once.
989
+
990
+ **Parameters**: `ids` (string[], required), `status` (`"active"` | `"paused"`, required).
991
+
992
+ **Returns**: `BulkUpdateEndpointStatusResponse` with per-endpoint `results`.
993
+
994
+ ```python
995
+ # Python
996
+ resp = await qn.admin.bulk_update_endpoint_status(ids=["ep-1", "ep-2"], status="paused")
997
+ ```
998
+
999
+ ##### `bulk_add_tag` / `bulkAddTag`
1000
+
1001
+ Applies a tag (created if missing) to many endpoints at once.
1002
+
1003
+ **Parameters**: `ids` (string[], required), `label` (string, required).
1004
+
1005
+ **Returns**: `BulkAddTagResponse`.
1006
+
1007
+ ```python
1008
+ # Python
1009
+ resp = await qn.admin.bulk_add_tag(ids=["ep-1", "ep-2"], label="prod")
1010
+ ```
1011
+
1012
+ ##### `bulk_remove_tag` / `bulkRemoveTag`
1013
+
1014
+ Removes a tag from many endpoints at once.
1015
+
1016
+ **Parameters**: `ids` (string[], required), `tag_id` (i32, required).
1017
+
1018
+ **Returns**: `BulkRemoveTagResponse`.
1019
+
1020
+ ```python
1021
+ # Python
1022
+ resp = await qn.admin.bulk_remove_tag(ids=["ep-1", "ep-2"], tag_id=42)
1023
+ ```
1024
+
1025
+ #### Account Tags
1026
+
1027
+ ##### `list_tags` / `listTags`
1028
+
1029
+ Lists every tag on the account along with usage counts.
1030
+
1031
+ **Parameters**: none.
1032
+
1033
+ **Returns**: `ListTagsResponse` with `data.tags: AccountTag[]`.
1034
+
1035
+ ```python
1036
+ # Python
1037
+ resp = await qn.admin.list_tags()
1038
+ ```
1039
+
1040
+ ##### `rename_tag` / `renameTag`
1041
+
1042
+ Renames an account-level tag.
1043
+
1044
+ **Parameters**: `tag_id` (i32, required); body: `label` (string, required).
1045
+
1046
+ **Returns**: `RenameTagResponse` with updated `AccountTag`.
1047
+
1048
+ ```python
1049
+ # Python
1050
+ resp = await qn.admin.rename_tag(42, label="staging")
1051
+ ```
1052
+
1053
+ ##### `delete_account_tag` / `deleteAccountTag`
1054
+
1055
+ Deletes a tag from the account. The tag must first be removed from any endpoints using it.
1056
+
1057
+ **Parameters**: `id` (i32, required).
1058
+
1059
+ **Returns**: `DeleteAccountTagResponse`.
1060
+
1061
+ ```python
1062
+ # Python
1063
+ await qn.admin.delete_account_tag(42)
1064
+ ```
1065
+
1066
+ ---
1067
+
1068
+ ### Streams Client
1069
+
1070
+ Accessed as `qn.streams`. Creates and manages blockchain data streams that deliver filtered on-chain events to configured destinations. Backed by `https://api.quicknode.com/streams/rest/v1/`.
1071
+
1072
+ #### Datasets, Regions, and Destinations
1073
+
1074
+ Enums used across stream methods:
1075
+
1076
+ - **`StreamRegion`**: `UsaEast`, `EuropeCentral`, `AsiaEast` (wire values: `usa_east`, `europe_central`, `asia_east`).
1077
+ - **`StreamDataset`**: `Block`, `BlockWithReceipts`, `Transactions`, `Logs`, `Receipts`, `TraceBlocks`, `DebugTraces`, `BlockWithReceiptsDebugTrace`, `BlockWithReceiptsTraceBlock`, `BlobSidecars`, `ProgramsWithLogs`, `Ledger`, `Events`, `Orders`, `Trades`, `BookUpdates`, `Twap`, `WriterActions`.
1078
+ - **`StreamStatus`**: `Active`, `Paused`, `Terminated`, `Completed`, `Blocked`.
1079
+ - **`FilterLanguage`**: `Javascript`, `Go`, `Wasm`.
1080
+ - **`StreamMetadataLocation`**: `Body`, `Header`, `None`.
1081
+
1082
+ Destinations are expressed via `DestinationAttributes`. Each variant wraps an attribute struct:
1083
+
1084
+ | Variant | Struct | Key fields |
1085
+ |---|---|---|
1086
+ | `Webhook` | `WebhookAttributes` | `url`, `max_retry`, `retry_interval_sec`, `post_timeout_sec`, `compression`, `security_token?` |
1087
+ | `S3` | `S3Attributes` | `endpoint`, `access_key`, `secret_key`, `bucket`, `object_prefix`, `compression`, `file_type`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
1088
+ | `Azure` | `AzureAttributes` | `storage_account`, `sas_token`, `container`, `compression`, `file_type`, `max_retry`, `retry_interval_sec`, `blob_prefix?` |
1089
+ | `Postgres` | `PostgresAttributes` | `host`, `port`, `username`, `password`, `database`, `table_name`, `sslmode`, `max_retry`, `retry_interval_sec` |
1090
+ | `Kafka` | `KafkaAttributes` | `bootstrap_servers`, `topic_name`, `compression_type`, `batch_size`, `linger_ms`, `max_message_bytes`, `timeout_sec`, `max_retry`, `retry_interval_sec`, `username?`, `password?`, `protocol?`, `mechanisms?` |
1091
+
1092
+ Wrapper naming per language:
1093
+
1094
+ - **Rust**: `DestinationAttributes::Webhook(WebhookAttributes { .. })` etc.
1095
+ - **Python**: `StreamWebhookDestination(WebhookAttributes(...))`, `StreamS3Destination(S3Attributes(...))`, etc.
1096
+ - **Node.js**: a discriminated object `{ destination: "webhook", attributes: { ... } }` using string discriminators.
1097
+ - **Ruby**: factory methods on `QuicknodeSdk::DestinationAttributes`, e.g. `QuicknodeSdk::DestinationAttributes.webhook(url: ..., ...)`.
1098
+
1099
+ #### Streams methods
1100
+
1101
+ ##### `create_stream` / `createStream`
1102
+
1103
+ Creates a new stream that delivers filtered data to the configured destination. Start from a specific block for backfills or from the tip for real-time streaming. Supports filters, reorg handling, distance-from-tip, elastic batching, notification emails, and extra destinations.
1104
+
1105
+ **Parameters**: `CreateStreamParams` — required: `name`, `region`, `network`, `dataset`, `start_range` (i64), `end_range` (i64, `-1` = follow tip), `destination_attributes`, `plan`, `threshold_fetch_buffer`. Common optional fields: `dataset_batch_size`, `include_stream_metadata`, `fix_block_reorgs`, `keep_distance_from_tip`, `elastic_batch_enabled`, `filter_function`, `filter_language`, `status`, `notification_email`, `extra_destinations`.
1106
+
1107
+ **Returns**: `Stream`.
1108
+
1109
+ ```python
1110
+ # Python
1111
+ from sdk import WebhookAttributes, StreamWebhookDestination
1112
+
1113
+ stream = await qn.streams.create_stream(
1114
+ name="My Stream",
1115
+ network="ethereum-mainnet",
1116
+ dataset="block",
1117
+ region="usa_east",
1118
+ start_range=24691804,
1119
+ end_range=24691904,
1120
+ destination_attributes=StreamWebhookDestination(
1121
+ WebhookAttributes(
1122
+ url="https://webhook.site/...",
1123
+ max_retry=3,
1124
+ retry_interval_sec=1,
1125
+ post_timeout_sec=10,
1126
+ compression="none",
1127
+ )
1128
+ ),
1129
+ plan="growth_plan",
1130
+ threshold_fetch_buffer=1000,
1131
+ status="active",
1132
+ )
1133
+ ```
1134
+
1135
+ ##### `list_streams` / `listStreams`
1136
+
1137
+ Paginated list of streams on the account.
1138
+
1139
+ **Parameters** (all optional): `offset` (i64), `limit` (i64), `order_by` (string), `order_direction` (`"asc"` | `"desc"`), `stream_type` (string).
1140
+
1141
+ **Returns**: `ListStreamsResponse` with `data: Stream[]` and `page_info`.
1142
+
1143
+ ```python
1144
+ # Python
1145
+ resp = await qn.streams.list_streams()
1146
+ ```
1147
+
1148
+ ##### `get_stream` / `getStream`
1149
+
1150
+ Fetches one stream by id.
1151
+
1152
+ **Parameters**: `id` (string, required).
1153
+
1154
+ **Returns**: `Stream`.
1155
+
1156
+ ```python
1157
+ # Python
1158
+ stream = await qn.streams.get_stream("stream-id")
1159
+ ```
1160
+
1161
+ ##### `update_stream` / `updateStream`
1162
+
1163
+ Partially updates a stream. Omitted fields are left unchanged.
1164
+
1165
+ **Parameters**: `id` (string, required); body: any field from `CreateStreamParams` (all optional).
1166
+
1167
+ **Returns**: updated `Stream`.
1168
+
1169
+ ```python
1170
+ # Python
1171
+ stream = await qn.streams.update_stream("stream-id", name="Renamed")
1172
+ ```
1173
+
1174
+ ##### `delete_stream` / `deleteStream`
1175
+
1176
+ Deletes one stream by id.
1177
+
1178
+ **Parameters**: `id` (string, required).
1179
+
1180
+ **Returns**: nothing.
1181
+
1182
+ ```python
1183
+ # Python
1184
+ await qn.streams.delete_stream("stream-id")
1185
+ ```
1186
+
1187
+ ##### `delete_all_streams` / `deleteAllStreams`
1188
+
1189
+ Deletes every stream on the account. Destructive and takes no arguments.
1190
+
1191
+ **Parameters**: none.
1192
+
1193
+ **Returns**: nothing.
1194
+
1195
+ ```python
1196
+ # Python
1197
+ await qn.streams.delete_all_streams()
1198
+ ```
1199
+
1200
+ ##### `activate_stream` / `activateStream`
1201
+
1202
+ Resumes delivery on a stream from its current position.
1203
+
1204
+ **Parameters**: `id` (string, required).
1205
+
1206
+ **Returns**: nothing.
1207
+
1208
+ ```python
1209
+ # Python
1210
+ await qn.streams.activate_stream("stream-id")
1211
+ ```
1212
+
1213
+ ##### `pause_stream` / `pauseStream`
1214
+
1215
+ Halts delivery on a stream.
1216
+
1217
+ **Parameters**: `id` (string, required).
1218
+
1219
+ **Returns**: nothing.
1220
+
1221
+ ```python
1222
+ # Python
1223
+ await qn.streams.pause_stream("stream-id")
1224
+ ```
1225
+
1226
+ ##### `test_filter` / `testFilter`
1227
+
1228
+ Runs a filter function against a block so it can be validated before being attached to a live stream.
1229
+
1230
+ **Parameters**: `network` (string, required), `dataset` (`StreamDataset`, required), `block` (string, required), `filter_function` (string, optional), `filter_language` (`FilterLanguage`, optional), `address_book_config` (optional).
1231
+
1232
+ **Returns**: `TestFilterResponse` with `result` and `logs`.
1233
+
1234
+ ```python
1235
+ # Python
1236
+ resp = await qn.streams.test_filter(
1237
+ network="ethereum-mainnet",
1238
+ dataset="block",
1239
+ block="17811625",
1240
+ )
1241
+ ```
1242
+
1243
+ ##### `get_enabled_count` / `getEnabledCount`
1244
+
1245
+ Counts currently enabled (active) streams, optionally filtered by type.
1246
+
1247
+ **Parameters**: `stream_type` (string, optional).
1248
+
1249
+ **Returns**: `EnabledCountResponse` with `total`.
1250
+
1251
+ ```python
1252
+ # Python
1253
+ resp = await qn.streams.get_enabled_count()
1254
+ ```
1255
+
1256
+ ---
1257
+
1258
+ ### Webhooks Client
1259
+
1260
+ Accessed as `qn.webhooks`. Creates webhooks from filter templates and manages their lifecycle. Backed by `https://api.quicknode.com/webhooks/rest/v1/`.
1261
+
1262
+ #### Templates and destination
1263
+
1264
+ `WebhookTemplateId` identifies the filter template:
1265
+
1266
+ | Variant | Wire value |
1267
+ |---|---|
1268
+ | `EvmWalletFilter` | `evmWalletFilter` |
1269
+ | `EvmContractEvents` | `evmContractEvents` |
1270
+ | `EvmAbiFilter` | `evmAbiFilter` |
1271
+ | `SolanaWalletFilter` | `solanaWalletFilter` |
1272
+ | `BitcoinWalletFilter` | `bitcoinWalletFilter` |
1273
+ | `XrplWalletFilter` | `xrplWalletFilter` |
1274
+ | `HyperliquidWalletEventsFilter` | `hyperliquidWalletEventsFilter` |
1275
+ | `StellarWalletTransactionsSourceAccountFilter` | `stellarWalletTransactionsSourceAccountFilter` |
1276
+
1277
+ `TemplateArgs` carries the arguments; construct one per template via the factory methods:
1278
+
1279
+ | Factory | Argument struct | Fields |
1280
+ |---|---|---|
1281
+ | `evm_wallet_filter` | `EvmWalletFilterTemplate` | `wallets: string[]` |
1282
+ | `evm_contract_events` | `EvmContractEventsTemplate` | `contracts: string[]`, `event_hashes?: string[]` |
1283
+ | `evm_abi_filter` | `EvmAbiFilterTemplate` | `abi: string` (JSON), `contracts: string[]` |
1284
+ | `solana_wallet_filter` | `SolanaWalletFilterTemplate` | `accounts: string[]` |
1285
+ | `bitcoin_wallet_filter` | `BitcoinWalletFilterTemplate` | `wallets: string[]` |
1286
+ | `xrpl_wallet_filter` | `XrplWalletFilterTemplate` | `wallets: string[]` |
1287
+ | `hyperliquid_wallet_events_filter` | `HyperliquidWalletEventsFilterTemplate` | `wallets: string[]` |
1288
+ | `stellar_wallet_transactions_filter` | `StellarWalletTransactionsFilterTemplate` | `source_accounts: string[]` |
1289
+
1290
+ `WebhookDestinationAttributes`: `url` (required), `security_token` (optional — auto-generated if omitted), `compression` (optional — `"none"` | `"gzip"`).
1291
+
1292
+ `WebhookStartFrom`: `Last` (resume from last delivered block) or `Latest` (start from newest).
1293
+
1294
+ In Ruby, `template_args` is passed as a JSON string under the key `template_args_json`; destination is passed as a JSON string under `destination_attributes_json`.
1295
+
1296
+ #### Webhooks methods
1297
+
1298
+ ##### `list_webhooks` / `listWebhooks`
1299
+
1300
+ Paginated list of webhooks.
1301
+
1302
+ **Parameters** (all optional): `limit` (i64), `offset` (i64).
1303
+
1304
+ **Returns**: `ListWebhooksResponse` with `data: Webhook[]` and `pageInfo: WebhookPageInfo { limit, offset, total }`.
1305
+
1306
+ ```python
1307
+ # Python
1308
+ resp = await qn.webhooks.list_webhooks()
1309
+ ```
1310
+
1311
+ ##### `get_webhook` / `getWebhook`
1312
+
1313
+ Fetches a webhook by id.
1314
+
1315
+ **Parameters**: `id` (string, required).
1316
+
1317
+ **Returns**: `Webhook`.
1318
+
1319
+ ```python
1320
+ # Python
1321
+ webhook = await qn.webhooks.get_webhook("wh-1")
1322
+ ```
1323
+
1324
+ ##### `create_webhook_from_template` / `createWebhookFromTemplate`
1325
+
1326
+ Creates a webhook from a predefined filter template.
1327
+
1328
+ **Parameters**: `name` (required), `network` (required), `destination_attributes` (`WebhookDestinationAttributes`, required), `template_args` (required — use the `TemplateArgs` enum variant for the chosen template), `notification_email` (optional).
1329
+
1330
+ **Returns**: `Webhook`.
1331
+
1332
+ ```python
1333
+ # Python
1334
+ from sdk import EvmWalletFilterArgs, EvmWalletFilterTemplate, WebhookDestinationAttributes
1335
+
1336
+ webhook = await qn.webhooks.create_webhook_from_template(
1337
+ name="Wallet Webhook",
1338
+ network="ethereum-mainnet",
1339
+ destination_attributes=WebhookDestinationAttributes(url="https://webhook.site/..."),
1340
+ template_args=EvmWalletFilterArgs(
1341
+ EvmWalletFilterTemplate(wallets=["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"])
1342
+ ),
1343
+ )
1344
+ ```
1345
+
1346
+ ##### `update_webhook` / `updateWebhook`
1347
+
1348
+ Partially updates a webhook's name, notification email, and/or destination. If `destination_attributes` is supplied without `security_token`, a new token is generated automatically.
1349
+
1350
+ **Parameters**: `id` (required); body — all optional: `name`, `notification_email`, `destination_attributes`. In Ruby, `destination_attributes` is passed as a JSON string under the key `destination_attributes_json`.
1351
+
1352
+ **Returns**: updated `Webhook`.
1353
+
1354
+ ```python
1355
+ # Python
1356
+ webhook = await qn.webhooks.update_webhook("wh-1", name="Renamed Webhook")
1357
+ ```
1358
+
1359
+ ##### `update_webhook_template` / `updateWebhookTemplate`
1360
+
1361
+ Updates the template args (and optionally name, email, destination) on an existing template-backed webhook.
1362
+
1363
+ **Parameters**: `webhook_id` (required), `template_args` (required); optional: `name`, `notification_email`, `destination_attributes`.
1364
+
1365
+ **Returns**: updated `Webhook`.
1366
+
1367
+ ```python
1368
+ # Python
1369
+ webhook = await qn.webhooks.update_webhook_template(
1370
+ "wh-1",
1371
+ template_args=EvmWalletFilterArgs(
1372
+ EvmWalletFilterTemplate(wallets=["0xnewwallet"])
1373
+ ),
1374
+ )
1375
+ ```
1376
+
1377
+ ##### `delete_webhook` / `deleteWebhook`
1378
+
1379
+ Deletes a webhook.
1380
+
1381
+ **Parameters**: `id` (required).
1382
+
1383
+ **Returns**: nothing.
1384
+
1385
+ ```python
1386
+ # Python
1387
+ await qn.webhooks.delete_webhook("wh-1")
1388
+ ```
1389
+
1390
+ ##### `delete_all_webhooks` / `deleteAllWebhooks`
1391
+
1392
+ Deletes every webhook on the account. Destructive and takes no arguments.
1393
+
1394
+ **Parameters**: none.
1395
+
1396
+ **Returns**: nothing.
1397
+
1398
+ ```python
1399
+ # Python
1400
+ await qn.webhooks.delete_all_webhooks()
1401
+ ```
1402
+
1403
+ ##### `pause_webhook` / `pauseWebhook`
1404
+
1405
+ Pauses a webhook so it stops delivering events.
1406
+
1407
+ **Parameters**: `id` (required).
1408
+
1409
+ **Returns**: nothing.
1410
+
1411
+ ```python
1412
+ # Python
1413
+ await qn.webhooks.pause_webhook("wh-1")
1414
+ ```
1415
+
1416
+ ##### `activate_webhook` / `activateWebhook`
1417
+
1418
+ Activates a paused or new webhook so it resumes delivering events. `start_from` determines where processing resumes.
1419
+
1420
+ **Parameters**: `id` (required), `start_from` (`WebhookStartFrom`, required — `Last` or `Latest`).
1421
+
1422
+ **Returns**: nothing.
1423
+
1424
+ ```python
1425
+ # Python
1426
+ await qn.webhooks.activate_webhook("wh-1", start_from="latest")
1427
+ ```
1428
+
1429
+ ##### `get_enabled_count` / `getEnabledCount`
1430
+
1431
+ Counts currently enabled webhooks.
1432
+
1433
+ **Parameters**: none.
1434
+
1435
+ **Returns**: `WebhookEnabledCountResponse` with `total`.
1436
+
1437
+ ```python
1438
+ # Python
1439
+ resp = await qn.webhooks.get_enabled_count()
1440
+ ```
1441
+
1442
+ ---
1443
+
1444
+ ### KV Store Client
1445
+
1446
+ Accessed as `qn.kvstore`. Provides two primitives — **sets** (single string values under a key) and **lists** (ordered collections of strings under a key). Backed by `https://api.quicknode.com/kv/rest/v1/`.
1447
+
1448
+ #### Sets
1449
+
1450
+ ##### `create_set` / `createSet`
1451
+
1452
+ Stores a single string value under a key.
1453
+
1454
+ **Parameters**: `key` (string, required), `value` (string, required).
1455
+
1456
+ **Returns**: nothing.
1457
+
1458
+ ```python
1459
+ # Python
1460
+ await qn.kvstore.create_set(key="my-key", value="hello")
1461
+ ```
1462
+
1463
+ ##### `get_sets` / `getSets`
1464
+
1465
+ Paginated page of key/value entries.
1466
+
1467
+ **Parameters** (all optional): `limit` (i64), `cursor` (string).
1468
+
1469
+ **Returns**: `GetSetsResponse` — `{ data: KvSetEntry[], cursor: string }`.
1470
+
1471
+ ```python
1472
+ # Python
1473
+ resp = await qn.kvstore.get_sets()
1474
+ ```
1475
+
1476
+ ##### `get_set` / `getSet`
1477
+
1478
+ Returns the value stored under a key.
1479
+
1480
+ **Parameters**: `key` (string, required).
1481
+
1482
+ **Returns**: `GetSetResponse` with `value`.
1483
+
1484
+ ```python
1485
+ # Python
1486
+ resp = await qn.kvstore.get_set("my-key")
1487
+ ```
1488
+
1489
+ ##### `bulk_sets` / `bulkSets`
1490
+
1491
+ Adds and/or deletes multiple sets in a single request.
1492
+
1493
+ **Parameters** (at least one required): `add_sets` (map<string,string>, optional), `delete_sets` (string[], optional).
1494
+
1495
+ **Returns**: nothing.
1496
+
1497
+ ```python
1498
+ # Python
1499
+ await qn.kvstore.bulk_sets(
1500
+ add_sets={"k1": "v1"},
1501
+ delete_sets=["old-key"],
1502
+ )
1503
+ ```
1504
+
1505
+ ##### `delete_set` / `deleteSet`
1506
+
1507
+ Deletes a single set.
1508
+
1509
+ **Parameters**: `key` (string, required).
1510
+
1511
+ **Returns**: nothing.
1512
+
1513
+ ```python
1514
+ # Python
1515
+ await qn.kvstore.delete_set("my-key")
1516
+ ```
1517
+
1518
+ #### Lists
1519
+
1520
+ ##### `create_list` / `createList`
1521
+
1522
+ Creates a list under a key, seeded with the initial items.
1523
+
1524
+ **Parameters**: `key` (string, required), `items` (string[], required).
1525
+
1526
+ **Returns**: nothing.
1527
+
1528
+ ```python
1529
+ # Python
1530
+ await qn.kvstore.create_list(key="my-list", items=["0xabc", "0xdef"])
1531
+ ```
1532
+
1533
+ ##### `get_lists` / `getLists`
1534
+
1535
+ Paginated page of list keys.
1536
+
1537
+ **Parameters** (all optional): `limit` (i64), `cursor` (string).
1538
+
1539
+ **Returns**: `GetListsResponse` — `{ data: { keys: string[] }, cursor: string }`.
1540
+
1541
+ ```python
1542
+ # Python
1543
+ resp = await qn.kvstore.get_lists()
1544
+ ```
1545
+
1546
+ ##### `get_list` / `getList`
1547
+
1548
+ Paginated page of items for a specific list.
1549
+
1550
+ **Parameters**: `key` (string, required); optional `limit` (i64), `cursor` (string).
1551
+
1552
+ **Returns**: `GetListResponse` — `{ data: { items: string[] }, cursor: string }`.
1553
+
1554
+ ```python
1555
+ # Python
1556
+ resp = await qn.kvstore.get_list("my-list")
1557
+ ```
1558
+
1559
+ ##### `update_list` / `updateList`
1560
+
1561
+ Adds and/or removes items in a single operation.
1562
+
1563
+ **Parameters**: `key` (string, required); optional: `add_items` (string[]), `remove_items` (string[]).
1564
+
1565
+ **Returns**: nothing.
1566
+
1567
+ ```python
1568
+ # Python
1569
+ await qn.kvstore.update_list(
1570
+ "my-list",
1571
+ add_items=["0x456"],
1572
+ remove_items=["0xabc"],
1573
+ )
1574
+ ```
1575
+
1576
+ ##### `add_list_item` / `addListItem`
1577
+
1578
+ Appends a single item to a list.
1579
+
1580
+ **Parameters**: `key` (string, required), `item` (string, required).
1581
+
1582
+ **Returns**: nothing.
1583
+
1584
+ ```python
1585
+ # Python
1586
+ await qn.kvstore.add_list_item("my-list", "0x123")
1587
+ ```
1588
+
1589
+ ##### `list_contains_item` / `listContainsItem`
1590
+
1591
+ Checks whether a list contains a specific item.
1592
+
1593
+ **Parameters**: `key` (string, required), `item` (string, required).
1594
+
1595
+ **Returns**: `ListContainsItemResponse` with `exists: bool`.
1596
+
1597
+ ```python
1598
+ # Python
1599
+ resp = await qn.kvstore.list_contains_item("my-list", "0x123")
1600
+ ```
1601
+
1602
+ ##### `delete_list_item` / `deleteListItem`
1603
+
1604
+ Removes a single item from a list.
1605
+
1606
+ **Parameters**: `key` (string, required), `item` (string, required).
1607
+
1608
+ **Returns**: nothing.
1609
+
1610
+ ```python
1611
+ # Python
1612
+ await qn.kvstore.delete_list_item("my-list", "0x123")
1613
+ ```
1614
+
1615
+ ##### `delete_list` / `deleteList`
1616
+
1617
+ Deletes a list and all of its items.
1618
+
1619
+ **Parameters**: `key` (string, required).
1620
+
1621
+ **Returns**: nothing.
1622
+
1623
+ ```python
1624
+ # Python
1625
+ await qn.kvstore.delete_list("my-list")
1626
+ ```
1627
+
1628
+ ## Error Handling
1629
+
1630
+ Every binding exposes a typed exception hierarchy derived from the core `SdkError`
1631
+ enum (`crates/core/src/errors.rs`). Catch the base class (`QuicknodeError`) for any SDK-originated failure, or a specific
1632
+ subclass to branch on transport vs. API semantics.
1633
+
1634
+ | Logical class | When it fires | Extra fields |
1635
+ |----------------------|-------------------------------------------------------------|----------------------|
1636
+ | `QuicknodeError` | base class; catches everything below | — |
1637
+ | `ConfigError` | invalid config or URL surfaced at construction time | — |
1638
+ | `HttpError` | transport failure that isn't a timeout/connect | — |
1639
+ | `TimeoutError` | request timed out (subclass of `HttpError`) | — |
1640
+ | `ConnectionError` | connection refused / DNS / TLS (subclass of `HttpError`) | — |
1641
+ | `ApiError` | non-2xx HTTP response | `status`, `body` |
1642
+ | `DecodeError` | 2xx response but JSON parse failed | `body` |
1643
+
1644
+ Class names: Importable from `sdk`: `QuicknodeError`, `ConfigError`, `HttpError`, `TimeoutError`, `ConnectionError`, `ApiError`, `DecodeError`.
1645
+
1646
+ ```python
1647
+ # Python
1648
+ from sdk import ApiError, TimeoutError
1649
+ try:
1650
+ await qn.admin.show_endpoint("missing")
1651
+ except ApiError as e:
1652
+ if e.status == 404:
1653
+ print(f"not found: {e.body}")
1654
+ else:
1655
+ raise
1656
+ except TimeoutError:
1657
+ print("timed out")
1658
+ ```
1659
+
1660
+ ## License
1661
+
1662
+ MIT
1663
+