Quicknode SDK
Project description
Quicknode SDK
A unified SDK for building on QuickNode.
Rust SDK with Python, Node.js, and Ruby bindings.
Table of Contents
- Project Structure
- Installation
- Quick Start
- Configuration
- API Reference
- Error Handling
- Development
- License
Project Structure
sdk/
├── crates/
│ ├── core/ # Pure Rust business logic
│ ├── python/ # PyO3 bindings
│ ├── node/ # napi-rs bindings
│ └── ruby/ # magnus bindings
├── python/sdk/ # Python package with type hints
├── npm/ # Node.js package with TypeScript types
├── ruby/ # Ruby package
└── pyproject.toml # maturin build config
Installation
Python: uv add quicknode-sdk
Node.js: npm install quicknode-sdk
Ruby: gem install quicknode-sdk (not yet published — see Development below)
Quick Start
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.
// Rust
use quicknode_sdk::{QuickNodeSdk, SdkFullConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let qn = QuickNodeSdk::from_env()?;
let resp = qn.admin.get_endpoints(&Default::default()).await?;
println!("{} endpoints", resp.data.len());
Ok(())
}
# Python
import asyncio
from sdk import QuickNodeSdk
async def main():
qn = QuickNodeSdk.from_env()
resp = await qn.admin.get_endpoints()
print(f"{len(resp.data)} endpoints")
asyncio.run(main())
// Node.js
import { QuickNodeSdk } from "quicknode-sdk";
const qn = QuickNodeSdk.fromEnv();
const resp = await qn.admin.getEndpoints();
console.log(`${resp.data.length} endpoints`);
# Ruby
require "json"
require "quicknode_sdk"
qn = QuickNodeSdk::SDK.from_env
resp = JSON.parse(qn.admin.get_endpoints({}))
puts "#{resp["data"].length} endpoints"
Configuration
There are two ways to configure the SDK.
Option A — Pass config directly
# Python
from sdk import QuickNodeSdk, SdkFullConfig, HttpConfig
qn = QuickNodeSdk(SdkFullConfig(api_key="your-key", http=HttpConfig(timeout_secs=30)))
// Node.js
import { QuickNodeSdk } from "quicknode-sdk";
const qn = new QuickNodeSdk({ apiKey: "your-key", http: { timeoutSecs: 30 } });
// Rust
let qn = QuickNodeSdk::new(&SdkFullConfig::builder().api_key("your-key").build())?;
Option B — Load from environment (from_env())
# Python
qn = QuickNodeSdk.from_env()
// Node.js
const qn = QuickNodeSdk.fromEnv();
# Ruby
qn = QuickNodeSdk::SDK.from_env
// Rust
let qn = QuickNodeSdk::from_env()?;
Environment variables (prefix QN_SDK__, separator __):
| Variable | Required | Default | Description |
|---|---|---|---|
QN_SDK__API_KEY |
yes | — | Your QuickNode API key |
QN_SDK__HTTP__TIMEOUT_SECS |
no | 30 | HTTP request timeout in seconds |
QN_SDK__HTTP__POOL_MAX_IDLE_PER_HOST |
no | — | Max idle HTTP connections per host |
QN_SDK__ADMIN__BASE_URL |
no | https://api.quicknode.com/v0/ |
Override admin API base URL (HTTPS, must end with /) |
QN_SDK__STREAMS__BASE_URL |
no | https://api.quicknode.com/streams/rest/v1/ |
Override streams base URL |
QN_SDK__WEBHOOKS__BASE_URL |
no | https://api.quicknode.com/webhooks/rest/v1/ |
Override webhooks base URL |
QN_SDK__KVSTORE__BASE_URL |
no | https://api.quicknode.com/kv/rest/v1/ |
Override KV store base URL |
API Reference
Each method below shows the call pattern in Rust, Python, Node.js, and Ruby in that order. Snippets assume qn was already constructed via the Quick Start. Optional parameters are skipped unless showing one is needed to illustrate usage.
Language conventions
- Rust: methods are
asyncand returnResult<T, SdkError>. Request structs use thebonbuilder pattern via::builder(). - Python: methods are
async— call withawait. Parameters are kwargs; responses are nativepyclassobjects with attribute access. - Node.js: methods are
asyncand take a single options object with camelCase keys. - Ruby: methods are blocking (not async). Parameters are a single Hash with symbol keys. Responses that carry data are returned as JSON strings — wrap calls with
JSON.parse. Unknown keys raiseArgumentError.
Admin Client
Accessed as qn.admin. Manages endpoints, tags, teams, billing, usage, metrics, security, and rate limits. Backed by https://api.quicknode.com/v0/.
Endpoints
get_endpoints / getEndpoints
Returns a paginated list of endpoints on the account with optional search, filters (networks, statuses, labels, tags, dedicated, flat-rate), sorting, and pagination.
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[]).
Returns: GetEndpointsResponse — { data: Endpoint[], pagination?: Pagination }.
// Rust
let params = GetEndpointsRequest::builder()
.limit(20)
.sort_by("created_at".to_string())
.sort_direction("desc".to_string())
.build();
let resp = qn.admin.get_endpoints(¶ms).await?;
# Python
resp = await qn.admin.get_endpoints(limit=20, sort_by="created_at", sort_direction="desc")
// Node.js
const resp = await qn.admin.getEndpoints({
limit: 20,
sortBy: "created_at",
sortDirection: "desc",
});
# Ruby
resp = JSON.parse(qn.admin.get_endpoints(limit: 20, sort_by: "created_at", sort_direction: "desc"))
create_endpoint / createEndpoint
Creates a new endpoint for the given blockchain and network.
Parameters: chain (string, optional), network (string, optional).
Returns: CreateEndpointResponse with data: SingleEndpoint.
// Rust
let params = CreateEndpointRequest::builder()
.chain("ethereum".to_string())
.network("mainnet".to_string())
.build();
let resp = qn.admin.create_endpoint(¶ms).await?;
# Python
resp = await qn.admin.create_endpoint(chain="ethereum", network="mainnet")
// Node.js
const resp = await qn.admin.createEndpoint({ chain: "ethereum", network: "mainnet" });
# Ruby
resp = JSON.parse(qn.admin.create_endpoint(chain: "ethereum", network: "mainnet"))
show_endpoint / showEndpoint
Fetches a single endpoint by id, including its full security configuration and rate limits.
Parameters: id (string, required).
Returns: ShowEndpointResponse with data: SingleEndpoint.
// Rust
let resp = qn.admin.show_endpoint("ep-123").await?;
# Python
resp = await qn.admin.show_endpoint("ep-123")
// Node.js
const resp = await qn.admin.showEndpoint("ep-123");
# Ruby
resp = JSON.parse(qn.admin.show_endpoint(id: "ep-123"))
update_endpoint / updateEndpoint
Updates editable fields on an endpoint. Currently supports label.
Parameters: id (string, required); body: label (string, optional).
Returns: nothing.
// Rust
let params = UpdateEndpointRequest::builder().label("my label".to_string()).build();
qn.admin.update_endpoint("ep-123", ¶ms).await?;
# Python
await qn.admin.update_endpoint("ep-123", label="my label")
// Node.js
await qn.admin.updateEndpoint("ep-123", { label: "my label" });
# Ruby
qn.admin.update_endpoint(id: "ep-123", label: "my label")
archive_endpoint / archiveEndpoint
Archives an endpoint. The HTTP verb is DELETE but the effect is archival, not permanent deletion.
Parameters: id (string, required).
Returns: nothing.
// Rust
qn.admin.archive_endpoint("ep-123").await?;
# Python
await qn.admin.archive_endpoint("ep-123")
// Node.js
await qn.admin.archiveEndpoint("ep-123");
# Ruby
qn.admin.archive_endpoint(id: "ep-123")
update_endpoint_status / updateEndpointStatus
Pauses or unpauses an endpoint.
Parameters: id (string, required); body: status (string, required — "active" or "paused").
Returns: UpdateEndpointStatusResponse.
// Rust
let params = UpdateEndpointStatusRequest::builder().status("paused".to_string()).build();
qn.admin.update_endpoint_status("ep-123", ¶ms).await?;
# Python
await qn.admin.update_endpoint_status("ep-123", status="paused")
// Node.js
await qn.admin.updateEndpointStatus("ep-123", { status: "paused" });
# Ruby
JSON.parse(qn.admin.update_endpoint_status(id: "ep-123", status: "paused"))
Endpoint Tags
Per-endpoint tag add/remove. For account-wide tag management see Account Tags.
create_tag / createTag
Tags an endpoint with the given label. Creates the tag on the account if it does not exist.
Parameters: id (string, required); body: label (string, optional).
Returns: nothing.
// Rust
let params = CreateTagRequest::builder().label("prod".to_string()).build();
qn.admin.create_tag("ep-123", ¶ms).await?;
# Python
await qn.admin.create_tag("ep-123", label="prod")
// Node.js
await qn.admin.createTag("ep-123", { label: "prod" });
# Ruby
qn.admin.create_tag(id: "ep-123", label: "prod")
delete_tag / deleteTag
Removes a tag from a specific endpoint.
Parameters: id (endpoint id, string, required), tag_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_tag("ep-123", "42").await?;
# Python
await qn.admin.delete_tag("ep-123", "42")
// Node.js
await qn.admin.deleteTag("ep-123", "42");
# Ruby
qn.admin.delete_tag(id: "ep-123", tag_id: "42")
Teams
list_teams / listTeams
Lists all teams on the account.
Parameters: none.
Returns: ListTeamsResponse with data: TeamSummary[].
// Rust
let resp = qn.admin.list_teams().await?;
# Python
resp = await qn.admin.list_teams()
// Node.js
const resp = await qn.admin.listTeams();
# Ruby
resp = JSON.parse(qn.admin.list_teams)
create_team / createTeam
Creates a new team.
Parameters: name (string, required).
Returns: CreateTeamResponse with data: CreateTeamData.
// Rust
let params = CreateTeamRequest::builder().name("Payments".to_string()).build();
let resp = qn.admin.create_team(¶ms).await?;
# Python
resp = await qn.admin.create_team(name="Payments")
// Node.js
const resp = await qn.admin.createTeam({ name: "Payments" });
# Ruby
resp = JSON.parse(qn.admin.create_team(name: "Payments"))
get_team / getTeam
Fetches team detail including pending invites.
Parameters: id (i64, required).
Returns: GetTeamResponse with data: TeamDetail.
// Rust
let resp = qn.admin.get_team(42).await?;
# Python
resp = await qn.admin.get_team(42)
// Node.js
const resp = await qn.admin.getTeam(42);
# Ruby
resp = JSON.parse(qn.admin.get_team(id: 42))
delete_team / deleteTeam
Deletes a team.
Parameters: id (i64, required).
Returns: DeleteTeamResponse.
// Rust
qn.admin.delete_team(42).await?;
# Python
await qn.admin.delete_team(42)
// Node.js
await qn.admin.deleteTeam(42);
# Ruby
qn.admin.delete_team(id: 42)
list_team_endpoints / listTeamEndpoints
Lists endpoints accessible to a team.
Parameters: id (i64, required).
Returns: ListTeamEndpointsResponse with data: TeamEndpoint[].
// Rust
let resp = qn.admin.list_team_endpoints(42).await?;
# Python
resp = await qn.admin.list_team_endpoints(42)
// Node.js
const resp = await qn.admin.listTeamEndpoints(42);
# Ruby
resp = JSON.parse(qn.admin.list_team_endpoints(id: 42))
update_team_endpoints / updateTeamEndpoints
Replaces the set of endpoints associated with a team. Pass an empty array to remove all.
Parameters: id (i64, required); body: endpoint_ids (string[], required).
Returns: UpdateTeamEndpointsResponse.
// Rust
let params = UpdateTeamEndpointsRequest::builder()
.endpoint_ids(vec!["ep-123".to_string(), "ep-456".to_string()])
.build();
qn.admin.update_team_endpoints(42, ¶ms).await?;
# Python
await qn.admin.update_team_endpoints(42, endpoint_ids=["ep-123", "ep-456"])
// Node.js
await qn.admin.updateTeamEndpoints(42, { endpointIds: ["ep-123", "ep-456"] });
# Ruby
qn.admin.update_team_endpoints(id: 42, endpoint_ids: ["ep-123", "ep-456"])
invite_team_member / inviteTeamMember
Invites a user to a team. Existing users only need email; new users require full_name and role.
Parameters: id (i64, required); body: email (string, required), full_name (string, optional), role (string, optional — admin | viewer | billing).
Returns: InviteTeamMemberResponse.
// Rust
let params = InviteTeamMemberRequest::builder()
.email("alice@example.com".to_string())
.role("viewer".to_string())
.build();
qn.admin.invite_team_member(42, ¶ms).await?;
# Python
await qn.admin.invite_team_member(42, email="alice@example.com", role="viewer")
// Node.js
await qn.admin.inviteTeamMember(42, { email: "alice@example.com", role: "viewer" });
# Ruby
qn.admin.invite_team_member(id: 42, email: "alice@example.com", role: "viewer")
remove_team_member / removeTeamMember
Removes a user from a team.
Parameters: id (team id, i64, required), user_id (i64, required).
Returns: RemoveTeamMemberResponse.
// Rust
qn.admin.remove_team_member(42, 7).await?;
# Python
await qn.admin.remove_team_member(42, 7)
// Node.js
await qn.admin.removeTeamMember(42, 7);
# Ruby
qn.admin.remove_team_member(id: 42, user_id: 7)
resend_team_invite / resendTeamInvite
Re-sends a pending team invitation.
Parameters: id (team id, i64, required), user_id (i64, required).
Returns: ResendTeamInviteResponse.
// Rust
qn.admin.resend_team_invite(42, 7).await?;
# Python
await qn.admin.resend_team_invite(42, 7)
// Node.js
await qn.admin.resendTeamInvite(42, 7);
# Ruby
qn.admin.resend_team_invite(id: 42, user_id: 7)
Usage
All usage methods accept optional start_time and end_time Unix timestamps. Omit both for account-to-date totals.
get_usage / getUsage
Aggregate account usage for a time window.
Returns: GetUsageResponse with data: UsageData (credits_used, credits_remaining, limit, overages, start_time, end_time).
// Rust
let resp = qn.admin.get_usage(&GetUsageRequest::default()).await?;
# Python
resp = await qn.admin.get_usage()
// Node.js
const resp = await qn.admin.getUsage();
# Ruby
resp = JSON.parse(qn.admin.get_usage({}))
get_usage_by_endpoint / getUsageByEndpoint
Per-endpoint usage breakdown.
Returns: GetUsageByEndpointResponse with data.endpoints: EndpointUsage[].
// Rust
let resp = qn.admin.get_usage_by_endpoint(&GetUsageRequest::default()).await?;
# Python
resp = await qn.admin.get_usage_by_endpoint()
// Node.js
const resp = await qn.admin.getUsageByEndpoint();
# Ruby
resp = JSON.parse(qn.admin.get_usage_by_endpoint({}))
get_usage_by_method / getUsageByMethod
Per-RPC-method usage breakdown.
Returns: GetUsageByMethodResponse with data.methods: MethodUsage[].
// Rust
let resp = qn.admin.get_usage_by_method(&GetUsageRequest::default()).await?;
# Python
resp = await qn.admin.get_usage_by_method()
// Node.js
const resp = await qn.admin.getUsageByMethod();
# Ruby
resp = JSON.parse(qn.admin.get_usage_by_method({}))
get_usage_by_chain / getUsageByChain
Per-chain usage breakdown.
Returns: GetUsageByChainResponse with data.chains: ChainUsage[].
// Rust
let resp = qn.admin.get_usage_by_chain(&GetUsageRequest::default()).await?;
# Python
resp = await qn.admin.get_usage_by_chain()
// Node.js
const resp = await qn.admin.getUsageByChain();
# Ruby
resp = JSON.parse(qn.admin.get_usage_by_chain({}))
get_usage_by_tag / getUsageByTag
Per-tag usage breakdown.
Returns: GetUsageByTagResponse with data.tags: TagUsage[].
// Rust
let resp = qn.admin.get_usage_by_tag(&GetUsageRequest::default()).await?;
# Python
resp = await qn.admin.get_usage_by_tag()
// Node.js
const resp = await qn.admin.getUsageByTag();
# Ruby
resp = JSON.parse(qn.admin.get_usage_by_tag({}))
Logs
get_endpoint_logs / getEndpointLogs
Fetches a page of request logs for an endpoint. Set include_details=true for full request/response payloads (truncated at 2 KB each).
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).
Returns: GetEndpointLogsResponse — { data: EndpointLog[], next_at?: string }.
// Rust
let params = GetEndpointLogsRequest::builder()
.from("2026-04-01T00:00:00Z".to_string())
.to("2026-04-02T00:00:00Z".to_string())
.limit(100)
.build();
let resp = qn.admin.get_endpoint_logs("ep-123", ¶ms).await?;
# Python
resp = await qn.admin.get_endpoint_logs(
"ep-123",
from_time="2026-04-01T00:00:00Z",
to_time="2026-04-02T00:00:00Z",
limit=100,
)
// Node.js
const resp = await qn.admin.getEndpointLogs("ep-123", {
from: "2026-04-01T00:00:00Z",
to: "2026-04-02T00:00:00Z",
limit: 100,
});
# Ruby
resp = JSON.parse(qn.admin.get_endpoint_logs(
id: "ep-123",
from_time: "2026-04-01T00:00:00Z",
to_time: "2026-04-02T00:00:00Z",
limit: 100
))
get_log_details / getLogDetails
Returns the full request/response payloads for a single log entry.
Parameters: id (endpoint id, required), request_id (log request uuid, required).
Returns: GetLogDetailsResponse with data: LogDetails.
// Rust
let resp = qn.admin.get_log_details("ep-123", "req-abc").await?;
# Python
resp = await qn.admin.get_log_details("ep-123", "req-abc")
// Node.js
const resp = await qn.admin.getLogDetails("ep-123", "req-abc");
# Ruby
resp = JSON.parse(qn.admin.get_log_details(id: "ep-123", request_id: "req-abc"))
Endpoint Security
get_endpoint_security / getEndpointSecurity
Returns the full security configuration for an endpoint: tokens, JWTs, referrers, domain masks, IPs, request filters, and their per-feature toggles.
Parameters: id (string, required).
Returns: GetEndpointSecurityResponse with data: EndpointSecurity.
// Rust
let resp = qn.admin.get_endpoint_security("ep-123").await?;
# Python
resp = await qn.admin.get_endpoint_security("ep-123")
// Node.js
const resp = await qn.admin.getEndpointSecurity("ep-123");
# Ruby
resp = JSON.parse(qn.admin.get_endpoint_security(id: "ep-123"))
Security Options
get_security_options / getSecurityOptions
Returns the list of security features and their enabled state for an endpoint.
Parameters: id (string, required).
Returns: GetSecurityOptionsResponse with data: SecurityOption[].
// Rust
let resp = qn.admin.get_security_options("ep-123").await?;
# Python
resp = await qn.admin.get_security_options("ep-123")
// Node.js
const resp = await qn.admin.getSecurityOptions("ep-123");
# Ruby
resp = JSON.parse(qn.admin.get_security_options(id: "ep-123"))
update_security_options / updateSecurityOptions
Enables or disables individual security features. Each field accepts "enabled" or "disabled".
Parameters: id (string, required); options: SecurityOptionsUpdate (tokens, referrers, jwts, ips, domain_masks, hsts, cors, request_filters, ip_custom_header).
Returns: UpdateSecurityOptionsResponse with updated SecurityOption[].
// Rust
let options = SecurityOptionsUpdate::builder()
.tokens("enabled".to_string())
.jwts("disabled".to_string())
.build();
let params = UpdateSecurityOptionsRequest { options };
qn.admin.update_security_options("ep-123", ¶ms).await?;
# Python
await qn.admin.update_security_options(
"ep-123",
tokens="enabled",
jwts="disabled",
)
// Node.js
await qn.admin.updateSecurityOptions("ep-123", {
options: { tokens: "enabled", jwts: "disabled" },
});
# Ruby
qn.admin.update_security_options(id: "ep-123", tokens: "enabled", jwts: "disabled")
Tokens
create_token / createToken
Generates a new auth token on an endpoint.
Parameters: id (endpoint id, required).
Returns: nothing.
// Rust
qn.admin.create_token("ep-123").await?;
# Python
await qn.admin.create_token("ep-123")
// Node.js
await qn.admin.createToken("ep-123");
# Ruby
qn.admin.create_token(id: "ep-123")
delete_token / deleteToken
Revokes a token on an endpoint.
Parameters: id (endpoint id, required), token_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_token("ep-123", "tok-1").await?;
# Python
await qn.admin.delete_token("ep-123", "tok-1")
// Node.js
await qn.admin.deleteToken("ep-123", "tok-1");
# Ruby
qn.admin.delete_token(id: "ep-123", token_id: "tok-1")
Referrers
create_referrer / createReferrer
Whitelists a referrer URL or domain on an endpoint.
Parameters: id (endpoint id, required); body: referrer (string, optional).
Returns: nothing.
// Rust
let params = CreateReferrerRequest::builder().referrer("example.com".to_string()).build();
qn.admin.create_referrer("ep-123", ¶ms).await?;
# Python
await qn.admin.create_referrer("ep-123", referrer="example.com")
// Node.js
await qn.admin.createReferrer("ep-123", { referrer: "example.com" });
# Ruby
qn.admin.create_referrer(id: "ep-123", referrer: "example.com")
delete_referrer / deleteReferrer
Removes a referrer from the whitelist.
Parameters: id (endpoint id, required), referrer_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_referrer("ep-123", "ref-1").await?;
# Python
await qn.admin.delete_referrer("ep-123", "ref-1")
// Node.js
await qn.admin.deleteReferrer("ep-123", "ref-1");
# Ruby
qn.admin.delete_referrer(id: "ep-123", referrer_id: "ref-1")
IPs
create_ip / createIp
Whitelists an IP address on an endpoint.
Parameters: id (endpoint id, required); body: ip (string, optional).
Returns: nothing.
// Rust
let params = CreateIpRequest::builder().ip("198.51.100.7".to_string()).build();
qn.admin.create_ip("ep-123", ¶ms).await?;
# Python
await qn.admin.create_ip("ep-123", ip="198.51.100.7")
// Node.js
await qn.admin.createIp("ep-123", { ip: "198.51.100.7" });
# Ruby
qn.admin.create_ip(id: "ep-123", ip: "198.51.100.7")
delete_ip / deleteIp
Removes an IP from the whitelist.
Parameters: id (endpoint id, required), ip_id (string, required).
Returns: DeleteBoolResponse.
// Rust
qn.admin.delete_ip("ep-123", "ip-1").await?;
# Python
await qn.admin.delete_ip("ep-123", "ip-1")
// Node.js
await qn.admin.deleteIp("ep-123", "ip-1");
# Ruby
resp = JSON.parse(qn.admin.delete_ip(id: "ep-123", ip_id: "ip-1"))
Domain Masks
create_domain_mask / createDomainMask
Adds a custom domain mask to an endpoint.
Parameters: id (endpoint id, required); body: domain_mask (string, optional).
Returns: nothing.
// Rust
let params = CreateDomainMaskRequest::builder()
.domain_mask("rpc.example.com".to_string())
.build();
qn.admin.create_domain_mask("ep-123", ¶ms).await?;
# Python
await qn.admin.create_domain_mask("ep-123", domain_mask="rpc.example.com")
// Node.js
await qn.admin.createDomainMask("ep-123", { domainMask: "rpc.example.com" });
# Ruby
qn.admin.create_domain_mask(id: "ep-123", domain_mask: "rpc.example.com")
delete_domain_mask / deleteDomainMask
Removes a domain mask.
Parameters: id (endpoint id, required), domain_mask_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_domain_mask("ep-123", "dm-1").await?;
# Python
await qn.admin.delete_domain_mask("ep-123", "dm-1")
// Node.js
await qn.admin.deleteDomainMask("ep-123", "dm-1");
# Ruby
qn.admin.delete_domain_mask(id: "ep-123", domain_mask_id: "dm-1")
JWTs
create_jwt / createJwt
Configures JWT validation on an endpoint.
Parameters: id (endpoint id, required); body: public_key (string, optional), kid (string, optional), name (string, optional).
Returns: nothing.
// Rust
let params = CreateJwtRequest::builder()
.public_key("-----BEGIN PUBLIC KEY-----\n...".to_string())
.kid("key-1".to_string())
.name("primary".to_string())
.build();
qn.admin.create_jwt("ep-123", ¶ms).await?;
# Python
await qn.admin.create_jwt(
"ep-123",
public_key="-----BEGIN PUBLIC KEY-----\n...",
kid="key-1",
name="primary",
)
// Node.js
await qn.admin.createJwt("ep-123", {
publicKey: "-----BEGIN PUBLIC KEY-----\n...",
kid: "key-1",
name: "primary",
});
# Ruby
qn.admin.create_jwt(
id: "ep-123",
public_key: "-----BEGIN PUBLIC KEY-----\n...",
kid: "key-1",
name: "primary"
)
delete_jwt / deleteJwt
Removes a JWT configuration.
Parameters: id (endpoint id, required), jwt_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_jwt("ep-123", "jwt-1").await?;
# Python
await qn.admin.delete_jwt("ep-123", "jwt-1")
// Node.js
await qn.admin.deleteJwt("ep-123", "jwt-1");
# Ruby
qn.admin.delete_jwt(id: "ep-123", jwt_id: "jwt-1")
Request Filters
Whitelist specific RPC methods on an endpoint. Requests for methods not on the list are blocked when the feature is enabled.
create_request_filter / createRequestFilter
Parameters: id (endpoint id, required); body: method (string[], optional). Ruby's Hash key is methods (plural).
Returns: CreateRequestFilterResponse with data.id.
// Rust
let params = CreateRequestFilterRequest::builder()
.method(vec!["eth_blockNumber".to_string(), "eth_getBalance".to_string()])
.build();
let resp = qn.admin.create_request_filter("ep-123", ¶ms).await?;
# Python
resp = await qn.admin.create_request_filter(
"ep-123",
method=["eth_blockNumber", "eth_getBalance"],
)
// Node.js
const resp = await qn.admin.createRequestFilter("ep-123", {
method: ["eth_blockNumber", "eth_getBalance"],
});
# Ruby
resp = JSON.parse(qn.admin.create_request_filter(
id: "ep-123",
methods: ["eth_blockNumber", "eth_getBalance"]
))
update_request_filter / updateRequestFilter
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).
Returns: nothing.
// Rust
let params = UpdateRequestFilterRequest::builder()
.method(vec!["eth_call".to_string()])
.build();
qn.admin.update_request_filter("ep-123", "f-1", ¶ms).await?;
# Python
await qn.admin.update_request_filter("ep-123", "f-1", method=["eth_call"])
// Node.js
await qn.admin.updateRequestFilter("ep-123", "f-1", { method: ["eth_call"] });
# Ruby
qn.admin.update_request_filter(id: "ep-123", request_filter_id: "f-1", methods: ["eth_call"])
delete_request_filter / deleteRequestFilter
Parameters: id (endpoint id, required), request_filter_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_request_filter("ep-123", "f-1").await?;
# Python
await qn.admin.delete_request_filter("ep-123", "f-1")
// Node.js
await qn.admin.deleteRequestFilter("ep-123", "f-1");
# Ruby
qn.admin.delete_request_filter(id: "ep-123", request_filter_id: "f-1")
Multichain
enable_multichain / enableMultichain
Enables multichain on an endpoint.
Parameters: id (endpoint id, required).
Returns: nothing.
// Rust
qn.admin.enable_multichain("ep-123").await?;
# Python
await qn.admin.enable_multichain("ep-123")
// Node.js
await qn.admin.enableMultichain("ep-123");
# Ruby
qn.admin.enable_multichain(id: "ep-123")
disable_multichain / disableMultichain
Disables multichain on an endpoint.
Parameters: id (endpoint id, required).
Returns: nothing.
// Rust
qn.admin.disable_multichain("ep-123").await?;
# Python
await qn.admin.disable_multichain("ep-123")
// Node.js
await qn.admin.disableMultichain("ep-123");
# Ruby
qn.admin.disable_multichain(id: "ep-123")
IP Custom Headers
create_or_update_ip_custom_header / createOrUpdateIpCustomHeader
Sets the custom header used to identify the client IP (e.g. when traffic is proxied).
Parameters: id (endpoint id, required); body: header_name (string, required).
Returns: CreateOrUpdateIpCustomHeaderResponse with data.header_name.
// Rust
let params = CreateOrUpdateIpCustomHeaderRequest::builder()
.header_name("X-Forwarded-For".to_string())
.build();
qn.admin.create_or_update_ip_custom_header("ep-123", ¶ms).await?;
# Python
await qn.admin.create_or_update_ip_custom_header("ep-123", header_name="X-Forwarded-For")
// Node.js
await qn.admin.createOrUpdateIpCustomHeader("ep-123", { headerName: "X-Forwarded-For" });
# Ruby
JSON.parse(qn.admin.create_or_update_ip_custom_header(
id: "ep-123",
header_name: "X-Forwarded-For"
))
delete_ip_custom_header / deleteIpCustomHeader
Removes the custom IP header configuration.
Parameters: id (endpoint id, required).
Returns: DeleteBoolResponse.
// Rust
qn.admin.delete_ip_custom_header("ep-123").await?;
# Python
await qn.admin.delete_ip_custom_header("ep-123")
// Node.js
await qn.admin.deleteIpCustomHeader("ep-123");
# Ruby
JSON.parse(qn.admin.delete_ip_custom_header(id: "ep-123"))
Method Rate Limits
get_method_rate_limits / getMethodRateLimits
Lists method-level rate limiters configured on an endpoint.
Parameters: id (endpoint id, required).
Returns: GetMethodRateLimitsResponse with data.rate_limiters: MethodRateLimiter[].
// Rust
let resp = qn.admin.get_method_rate_limits("ep-123").await?;
# Python
resp = await qn.admin.get_method_rate_limits("ep-123")
// Node.js
const resp = await qn.admin.getMethodRateLimits("ep-123");
# Ruby
resp = JSON.parse(qn.admin.get_method_rate_limits(id: "ep-123"))
create_method_rate_limit / createMethodRateLimit
Creates a new method-level rate limiter.
Parameters: id (endpoint id, required); body: interval (string, e.g. "second"), methods (string[]), rate (i32).
Returns: CreateMethodRateLimitResponse with data: MethodRateLimiter.
// Rust
let params = CreateMethodRateLimitRequest::builder()
.interval("second".to_string())
.methods(vec!["eth_call".to_string()])
.rate(10)
.build();
let resp = qn.admin.create_method_rate_limit("ep-123", ¶ms).await?;
# Python
resp = await qn.admin.create_method_rate_limit(
"ep-123",
interval="second",
methods=["eth_call"],
rate=10,
)
// Node.js
const resp = await qn.admin.createMethodRateLimit("ep-123", {
interval: "second",
methods: ["eth_call"],
rate: 10,
});
# Ruby
resp = JSON.parse(qn.admin.create_method_rate_limit(
id: "ep-123",
interval: "second",
methods: ["eth_call"],
rate: 10
))
update_method_rate_limit / updateMethodRateLimit
Updates an existing rate limiter. Only provided fields change.
Parameters: id (endpoint id, required), method_rate_limit_id (string, required); body: methods (string[], optional), status ("enabled" | "disabled", optional), rate (i32, optional).
Returns: UpdateMethodRateLimitResponse.
// Rust
let params = UpdateMethodRateLimitRequest::builder().rate(50).build();
qn.admin.update_method_rate_limit("ep-123", "rl-1", ¶ms).await?;
# Python
await qn.admin.update_method_rate_limit("ep-123", "rl-1", rate=50)
// Node.js
await qn.admin.updateMethodRateLimit("ep-123", "rl-1", { rate: 50 });
# Ruby
JSON.parse(qn.admin.update_method_rate_limit(id: "ep-123", method_rate_limit_id: "rl-1", rate: 50))
delete_method_rate_limit / deleteMethodRateLimit
Deletes a rate limiter.
Parameters: id (endpoint id, required), method_rate_limit_id (string, required).
Returns: nothing.
// Rust
qn.admin.delete_method_rate_limit("ep-123", "rl-1").await?;
# Python
await qn.admin.delete_method_rate_limit("ep-123", "rl-1")
// Node.js
await qn.admin.deleteMethodRateLimit("ep-123", "rl-1");
# Ruby
qn.admin.delete_method_rate_limit(id: "ep-123", method_rate_limit_id: "rl-1")
Endpoint Rate Limits
update_rate_limits / updateRateLimits
Updates the endpoint-level RPS / RPM / RPD caps.
Parameters: id (endpoint id, required); rate_limits: RateLimitSettings (rps, rpm, rpd, all optional).
Returns: nothing.
// Rust
let rate_limits = RateLimitSettings::builder().rps(100).rpm(5000).build();
let params = UpdateRateLimitsRequest { rate_limits };
qn.admin.update_rate_limits("ep-123", ¶ms).await?;
# Python
await qn.admin.update_rate_limits("ep-123", rps=100, rpm=5000)
// Node.js
await qn.admin.updateRateLimits("ep-123", { rateLimits: { rps: 100, rpm: 5000 } });
# Ruby
qn.admin.update_rate_limits(id: "ep-123", rps: 100, rpm: 5000)
Metrics
get_endpoint_metrics / getEndpointMetrics
Returns metric series for an endpoint over a time period.
Parameters: id (endpoint id, required); body: period ("hour" | "day" | "week" | "month"), metric (e.g. "method_calls_over_time", "response_status_breakdown").
Returns: GetEndpointMetricsResponse with data: EndpointMetric[].
// Rust
let params = GetEndpointMetricsRequest {
period: "day".to_string(),
metric: "method_calls_over_time".to_string(),
};
let resp = qn.admin.get_endpoint_metrics("ep-123", ¶ms).await?;
# Python
resp = await qn.admin.get_endpoint_metrics(
"ep-123",
period="day",
metric="method_calls_over_time",
)
// Node.js
const resp = await qn.admin.getEndpointMetrics("ep-123", {
period: "day",
metric: "method_calls_over_time",
});
# Ruby
resp = JSON.parse(qn.admin.get_endpoint_metrics(
id: "ep-123",
period: "day",
metric: "method_calls_over_time"
))
get_account_metrics / getAccountMetrics
Returns account-level metric series. Supports an optional percentile (e.g. "p50", "p95", "p99") for latency metrics.
Parameters: period (required), metric (required), percentile (string, optional).
Returns: GetAccountMetricsResponse with data: EndpointMetric[].
// Rust
let params = GetAccountMetricsRequest {
period: "day".to_string(),
metric: "credits_over_time".to_string(),
percentile: None,
};
let resp = qn.admin.get_account_metrics(¶ms).await?;
# Python
resp = await qn.admin.get_account_metrics(period="day", metric="credits_over_time")
// Node.js
const resp = await qn.admin.getAccountMetrics({
period: "day",
metric: "credits_over_time",
});
# Ruby
resp = JSON.parse(qn.admin.get_account_metrics(period: "day", metric: "credits_over_time"))
Chains
list_chains / listChains
Lists the blockchains supported by QuickNode along with their networks.
Parameters: none.
Returns: ListChainsResponse with data: Chain[].
// Rust
let resp = qn.admin.list_chains().await?;
# Python
resp = await qn.admin.list_chains()
// Node.js
const resp = await qn.admin.listChains();
# Ruby
resp = JSON.parse(qn.admin.list_chains)
Billing
list_invoices / listInvoices
Lists invoices on the account.
Parameters: none.
Returns: ListInvoicesResponse with data.invoices: Invoice[].
// Rust
let resp = qn.admin.list_invoices().await?;
# Python
resp = await qn.admin.list_invoices()
// Node.js
const resp = await qn.admin.listInvoices();
# Ruby
resp = JSON.parse(qn.admin.list_invoices)
list_payments / listPayments
Lists payments on the account.
Parameters: none.
Returns: ListPaymentsResponse with data.payments: Payment[].
// Rust
let resp = qn.admin.list_payments().await?;
# Python
resp = await qn.admin.list_payments()
// Node.js
const resp = await qn.admin.listPayments();
# Ruby
resp = JSON.parse(qn.admin.list_payments)
Bulk Operations
bulk_update_endpoint_status / bulkUpdateEndpointStatus
Activates or pauses many endpoints at once.
Parameters: ids (string[], required), status ("active" | "paused", required).
Returns: BulkUpdateEndpointStatusResponse with per-endpoint results.
// Rust
let params = BulkUpdateEndpointStatusRequest::builder()
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
.status("paused".to_string())
.build();
let resp = qn.admin.bulk_update_endpoint_status(¶ms).await?;
# Python
resp = await qn.admin.bulk_update_endpoint_status(ids=["ep-1", "ep-2"], status="paused")
// Node.js
const resp = await qn.admin.bulkUpdateEndpointStatus({
ids: ["ep-1", "ep-2"],
status: "paused",
});
# Ruby
resp = JSON.parse(qn.admin.bulk_update_endpoint_status(ids: ["ep-1", "ep-2"], status: "paused"))
bulk_add_tag / bulkAddTag
Applies a tag (created if missing) to many endpoints at once.
Parameters: ids (string[], required), label (string, required).
Returns: BulkAddTagResponse.
// Rust
let params = BulkAddTagRequest::builder()
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
.label("prod".to_string())
.build();
let resp = qn.admin.bulk_add_tag(¶ms).await?;
# Python
resp = await qn.admin.bulk_add_tag(ids=["ep-1", "ep-2"], label="prod")
// Node.js
const resp = await qn.admin.bulkAddTag({ ids: ["ep-1", "ep-2"], label: "prod" });
# Ruby
resp = JSON.parse(qn.admin.bulk_add_tag(ids: ["ep-1", "ep-2"], label: "prod"))
bulk_remove_tag / bulkRemoveTag
Removes a tag from many endpoints at once.
Parameters: ids (string[], required), tag_id (i32, required).
Returns: BulkRemoveTagResponse.
// Rust
let params = BulkRemoveTagRequest::builder()
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
.tag_id(42)
.build();
let resp = qn.admin.bulk_remove_tag(¶ms).await?;
# Python
resp = await qn.admin.bulk_remove_tag(ids=["ep-1", "ep-2"], tag_id=42)
// Node.js
const resp = await qn.admin.bulkRemoveTag({ ids: ["ep-1", "ep-2"], tagId: 42 });
# Ruby
resp = JSON.parse(qn.admin.bulk_remove_tag(ids: ["ep-1", "ep-2"], tag_id: 42))
Account Tags
list_tags / listTags
Lists every tag on the account along with usage counts.
Parameters: none.
Returns: ListTagsResponse with data.tags: AccountTag[].
// Rust
let resp = qn.admin.list_tags().await?;
# Python
resp = await qn.admin.list_tags()
// Node.js
const resp = await qn.admin.listTags();
# Ruby
resp = JSON.parse(qn.admin.list_tags)
rename_tag / renameTag
Renames an account-level tag.
Parameters: tag_id (i32, required); body: label (string, required).
Returns: RenameTagResponse with updated AccountTag.
// Rust
let params = RenameTagRequest::builder().label("staging".to_string()).build();
let resp = qn.admin.rename_tag(42, ¶ms).await?;
# Python
resp = await qn.admin.rename_tag(42, label="staging")
// Node.js
const resp = await qn.admin.renameTag(42, { label: "staging" });
# Ruby
resp = JSON.parse(qn.admin.rename_tag(tag_id: 42, label: "staging"))
delete_account_tag / deleteAccountTag
Deletes a tag from the account. The tag must first be removed from any endpoints using it.
Parameters: id (i32, required).
Returns: DeleteAccountTagResponse.
// Rust
qn.admin.delete_account_tag(42).await?;
# Python
await qn.admin.delete_account_tag(42)
// Node.js
await qn.admin.deleteAccountTag(42);
# Ruby
JSON.parse(qn.admin.delete_account_tag(id: 42))
Streams Client
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/.
Datasets, Regions, and Destinations
Enums used across stream methods:
StreamRegion:UsaEast,EuropeCentral,AsiaEast(wire values:usa_east,europe_central,asia_east).StreamDataset:Block,BlockWithReceipts,Transactions,Logs,Receipts,TraceBlocks,DebugTraces,BlockWithReceiptsDebugTrace,BlockWithReceiptsTraceBlock,BlobSidecars,ProgramsWithLogs,Ledger,Events,Orders,Trades,BookUpdates,Twap,WriterActions.StreamStatus:Active,Paused,Terminated,Completed,Blocked.FilterLanguage:Javascript,Go,Wasm.StreamMetadataLocation:Body,Header,None.
Destinations are expressed via DestinationAttributes. Each variant wraps an attribute struct:
| Variant | Struct | Key fields |
|---|---|---|
Webhook |
WebhookAttributes |
url, max_retry, retry_interval_sec, post_timeout_sec, compression, security_token? |
S3 |
S3Attributes |
endpoint, access_key, secret_key, bucket, object_prefix, compression, file_type, max_retry, retry_interval_sec, use_ssl? |
Azure |
AzureAttributes |
storage_account, sas_token, container, compression, file_type, max_retry, retry_interval_sec, blob_prefix? |
Postgres |
PostgresAttributes |
host, port, username, password, database, schema, table, max_retry, retry_interval_sec, use_ssl? |
Mysql |
MysqlAttributes |
host, port, username, password, database, table, max_retry, retry_interval_sec, use_ssl? |
Mongo |
MongoAttributes |
connection_string, database, collection, max_retry, retry_interval_sec |
Clickhouse |
ClickhouseAttributes |
host, port, username, password, database, table, max_retry, retry_interval_sec, use_ssl? |
Snowflake |
SnowflakeAttributes |
account, warehouse, database, schema, table, username, private_key, max_retry, retry_interval_sec |
Kafka |
KafkaAttributes |
bootstrap_servers, topic, compression, max_retry, retry_interval_sec |
Redis |
RedisAttributes |
host, port, username, password, key, max_retry, retry_interval_sec, use_ssl? |
Wrapper naming per language:
- Rust:
DestinationAttributes::Webhook(WebhookAttributes { .. })etc. - Python:
StreamWebhookDestination(WebhookAttributes(...)),StreamS3Destination(S3Attributes(...)), etc. - Node.js: a discriminated object
{ destination: "webhook", attributes: { ... } }using string discriminators. - Ruby: factory methods on
QuickNodeSdk::DestinationAttributes, e.g.QuickNodeSdk::DestinationAttributes.webhook(url: ..., ...).
Streams methods
create_stream / createStream
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.
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.
Returns: Stream.
// Rust
let params = CreateStreamParams::builder()
.name("My Stream".to_string())
.region(StreamRegion::UsaEast)
.network("ethereum-mainnet".to_string())
.dataset(StreamDataset::Block)
.start_range(24691804)
.end_range(24691904)
.destination_attributes(DestinationAttributes::Webhook(WebhookAttributes {
url: "https://webhook.site/...".to_string(),
max_retry: 3,
retry_interval_sec: 1,
post_timeout_sec: 10,
compression: "none".to_string(),
security_token: None,
}))
.plan("growth_plan".to_string())
.threshold_fetch_buffer(1000)
.status(StreamStatus::Active)
.build();
let stream = qn.streams.create_stream(¶ms).await?;
# Python
from sdk import WebhookAttributes, StreamWebhookDestination
stream = await qn.streams.create_stream(
name="My Stream",
network="ethereum-mainnet",
dataset="block",
region="usa_east",
start_range=24691804,
end_range=24691904,
destination_attributes=StreamWebhookDestination(
WebhookAttributes(
url="https://webhook.site/...",
max_retry=3,
retry_interval_sec=1,
post_timeout_sec=10,
compression="none",
)
),
plan="growth_plan",
threshold_fetch_buffer=1000,
status="active",
)
// Node.js
import { StreamDataset, StreamRegion, StreamStatus } from "quicknode-sdk";
const stream = await qn.streams.createStream({
name: "My Stream",
network: "ethereum-mainnet",
dataset: StreamDataset.Block,
region: StreamRegion.UsaEast,
startRange: 24691804,
endRange: 24691904,
destinationAttributes: {
destination: "webhook",
attributes: {
url: "https://webhook.site/...",
maxRetry: 3,
retryIntervalSec: 1,
postTimeoutSec: 10,
compression: "none",
},
},
plan: "growth_plan",
thresholdFetchBuffer: 1000,
status: StreamStatus.Active,
});
# Ruby
dest = QuickNodeSdk::DestinationAttributes.webhook(
url: "https://webhook.site/...",
max_retry: 3,
retry_interval_sec: 1,
post_timeout_sec: 10,
compression: "none"
)
stream = JSON.parse(qn.streams.create_stream(
name: "My Stream",
network: "ethereum-mainnet",
dataset: "block",
region: "usa_east",
start_range: 24691804,
end_range: 24691904,
destination_attributes: dest,
plan: "growth_plan",
threshold_fetch_buffer: 1000,
status: "active"
))
list_streams / listStreams
Paginated list of streams on the account.
Parameters (all optional): offset (i64), limit (i64), order_by (string), order_direction ("asc" | "desc"), stream_type (string).
Returns: ListStreamsResponse with data: Stream[] and page_info.
// Rust
let resp = qn.streams.list_streams(&ListStreamsParams::default()).await?;
# Python
resp = await qn.streams.list_streams()
// Node.js
const resp = await qn.streams.listStreams();
# Ruby
resp = JSON.parse(qn.streams.list_streams({}))
get_stream / getStream
Fetches one stream by id.
Parameters: id (string, required).
Returns: Stream.
// Rust
let stream = qn.streams.get_stream("stream-id").await?;
# Python
stream = await qn.streams.get_stream("stream-id")
// Node.js
const stream = await qn.streams.getStream("stream-id");
# Ruby
stream = JSON.parse(qn.streams.get_stream(id: "stream-id"))
update_stream / updateStream
Partially updates a stream. Omitted fields are left unchanged.
Parameters: id (string, required); body: any field from CreateStreamParams (all optional).
Returns: updated Stream.
// Rust
let params = UpdateStreamParams {
name: Some("Renamed".to_string()),
..Default::default()
};
let stream = qn.streams.update_stream("stream-id", ¶ms).await?;
# Python
stream = await qn.streams.update_stream("stream-id", name="Renamed")
// Node.js
const stream = await qn.streams.updateStream("stream-id", { name: "Renamed" });
# Ruby
stream = JSON.parse(qn.streams.update_stream(id: "stream-id", name: "Renamed"))
delete_stream / deleteStream
Deletes one stream by id.
Parameters: id (string, required).
Returns: nothing.
// Rust
qn.streams.delete_stream("stream-id").await?;
# Python
await qn.streams.delete_stream("stream-id")
// Node.js
await qn.streams.deleteStream("stream-id");
# Ruby
qn.streams.delete_stream(id: "stream-id")
delete_all_streams / deleteAllStreams
Deletes every stream on the account. Destructive and takes no arguments.
Parameters: none.
Returns: nothing.
// Rust
qn.streams.delete_all_streams().await?;
# Python
await qn.streams.delete_all_streams()
// Node.js
await qn.streams.deleteAllStreams();
# Ruby
qn.streams.delete_all_streams
activate_stream / activateStream
Resumes delivery on a stream from its current position.
Parameters: id (string, required).
Returns: nothing.
// Rust
qn.streams.activate_stream("stream-id").await?;
# Python
await qn.streams.activate_stream("stream-id")
// Node.js
await qn.streams.activateStream("stream-id");
# Ruby
qn.streams.activate_stream(id: "stream-id")
pause_stream / pauseStream
Halts delivery on a stream.
Parameters: id (string, required).
Returns: nothing.
// Rust
qn.streams.pause_stream("stream-id").await?;
# Python
await qn.streams.pause_stream("stream-id")
// Node.js
await qn.streams.pauseStream("stream-id");
# Ruby
qn.streams.pause_stream(id: "stream-id")
test_filter / testFilter
Runs a filter function against a block so it can be validated before being attached to a live stream.
Parameters: network (string, required), dataset (StreamDataset, required), block (string, required), filter_function (string, optional), filter_language (FilterLanguage, optional), address_book_config (optional).
Returns: TestFilterResponse with result and logs.
// Rust
let params = TestFilterParams {
network: "ethereum-mainnet".to_string(),
dataset: StreamDataset::Block,
block: "17811625".to_string(),
filter_function: None,
filter_language: None,
address_book_config: None,
};
let resp = qn.streams.test_filter(¶ms).await?;
# Python
resp = await qn.streams.test_filter(
network="ethereum-mainnet",
dataset="block",
block="17811625",
)
// Node.js
import { StreamDataset } from "quicknode-sdk";
const resp = await qn.streams.testFilter({
network: "ethereum-mainnet",
dataset: StreamDataset.Block,
block: "17811625",
});
# Ruby
resp = JSON.parse(qn.streams.test_filter(
network: "ethereum-mainnet",
dataset: "block",
block: "17811625"
))
get_enabled_count / getEnabledCount
Counts currently enabled (active) streams, optionally filtered by type.
Parameters: stream_type (string, optional).
Returns: EnabledCountResponse with total.
// Rust
let resp = qn.streams.get_enabled_count(None).await?;
# Python
resp = await qn.streams.get_enabled_count()
// Node.js
const resp = await qn.streams.getEnabledCount();
# Ruby
resp = JSON.parse(qn.streams.get_enabled_count({}))
Webhooks Client
Accessed as qn.webhooks. Creates webhooks from filter templates and manages their lifecycle. Backed by https://api.quicknode.com/webhooks/rest/v1/.
Templates and destination
WebhookTemplateId identifies the filter template:
| Variant | Wire value |
|---|---|
EvmWalletFilter |
evmWalletFilter |
EvmContractEvents |
evmContractEvents |
EvmAbiFilter |
evmAbiFilter |
SolanaWalletFilter |
solanaWalletFilter |
BitcoinWalletFilter |
bitcoinWalletFilter |
XrplWalletFilter |
xrplWalletFilter |
HyperliquidWalletEventsFilter |
hyperliquidWalletEventsFilter |
StellarWalletTransactionsSourceAccountFilter |
stellarWalletTransactionsSourceAccountFilter |
TemplateArgs carries the arguments; construct one per template via the factory methods:
| Factory | Argument struct | Fields |
|---|---|---|
evm_wallet_filter |
EvmWalletFilterTemplate |
wallets: string[] |
evm_contract_events |
EvmContractEventsTemplate |
contracts: string[], event_hashes?: string[] |
evm_abi_filter |
EvmAbiFilterTemplate |
abi: string (JSON), contracts: string[] |
solana_wallet_filter |
SolanaWalletFilterTemplate |
accounts: string[] |
bitcoin_wallet_filter |
BitcoinWalletFilterTemplate |
wallets: string[] |
xrpl_wallet_filter |
XrplWalletFilterTemplate |
wallets: string[] |
hyperliquid_wallet_events_filter |
HyperliquidWalletEventsFilterTemplate |
wallets: string[] |
stellar_wallet_transactions_filter |
StellarWalletTransactionsFilterTemplate |
source_accounts: string[] |
WebhookDestinationAttributes: url (required), security_token (optional — auto-generated if omitted), compression (optional — "none" | "gzip").
WebhookStartFrom: Last (resume from last delivered block) or Latest (start from newest).
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.
Webhooks methods
list_webhooks / listWebhooks
Paginated list of webhooks.
Parameters (all optional): limit (i64), offset (i64).
Returns: ListWebhooksResponse with data: Webhook[] and pageInfo.
// Rust
let resp = qn.webhooks.list_webhooks(&GetWebhooksParams::default()).await?;
# Python
resp = await qn.webhooks.list_webhooks()
// Node.js
const resp = await qn.webhooks.listWebhooks();
# Ruby
resp = JSON.parse(qn.webhooks.list_webhooks({}))
get_webhook / getWebhook
Fetches a webhook by id.
Parameters: id (string, required).
Returns: Webhook.
// Rust
let webhook = qn.webhooks.get_webhook("wh-1").await?;
# Python
webhook = await qn.webhooks.get_webhook("wh-1")
// Node.js
const webhook = await qn.webhooks.getWebhook("wh-1");
# Ruby
webhook = JSON.parse(qn.webhooks.get_webhook(id: "wh-1"))
create_webhook_from_template / createWebhookFromTemplate
Creates a webhook from a predefined filter template.
Parameters: name (required), network (required), destination_attributes (WebhookDestinationAttributes, required), template_args (TemplateArgs, required), notification_email (optional).
Returns: Webhook.
// Rust
let template_args = TemplateArgs::evm_wallet_filter(&EvmWalletFilterTemplate {
wallets: vec!["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string()],
})?;
let params = CreateWebhookFromTemplateParams {
name: "Wallet Webhook".to_string(),
network: "ethereum-mainnet".to_string(),
notification_email: None,
destination_attributes: WebhookDestinationAttributes {
url: "https://webhook.site/...".to_string(),
security_token: None,
compression: None,
},
template_args,
};
let webhook = qn.webhooks.create_webhook_from_template(¶ms).await?;
# Python
from sdk import EvmWalletFilterTemplate, TemplateArgs, WebhookDestinationAttributes
webhook = await qn.webhooks.create_webhook_from_template(
name="Wallet Webhook",
network="ethereum-mainnet",
destination_attributes=WebhookDestinationAttributes(url="https://webhook.site/..."),
template_args=TemplateArgs.evm_wallet_filter(
EvmWalletFilterTemplate(wallets=["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"])
),
)
// Node.js
import { TemplateArgs } from "quicknode-sdk";
const webhook = await qn.webhooks.createWebhookFromTemplate({
name: "Wallet Webhook",
network: "ethereum-mainnet",
destinationAttributes: { url: "https://webhook.site/..." },
templateArgs: TemplateArgs.evmWalletFilter({
wallets: ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"],
}),
});
# Ruby
destination_attributes = JSON.generate({
url: "https://webhook.site/...",
compression: "none"
})
template_args = JSON.generate({
template_id: "evmWalletFilter",
value: JSON.generate({ wallets: ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"] })
})
webhook = JSON.parse(qn.webhooks.create_webhook_from_template(
name: "Wallet Webhook",
network: "ethereum-mainnet",
destination_attributes_json: destination_attributes,
template_args_json: template_args
))
update_webhook / updateWebhook
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.
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.
Returns: updated Webhook.
// Rust
let params = UpdateWebhookParams {
name: Some("Renamed Webhook".to_string()),
..Default::default()
};
let webhook = qn.webhooks.update_webhook("wh-1", ¶ms).await?;
# Python
webhook = await qn.webhooks.update_webhook("wh-1", name="Renamed Webhook")
// Node.js
const webhook = await qn.webhooks.updateWebhook("wh-1", { name: "Renamed Webhook" });
# Ruby
webhook = JSON.parse(qn.webhooks.update_webhook(id: "wh-1", name: "Renamed Webhook"))
update_webhook_template / updateWebhookTemplate
Updates the template args (and optionally name, email, destination) on an existing template-backed webhook.
Parameters: webhook_id (required), template_args (required); optional: name, notification_email, destination_attributes.
Returns: updated Webhook.
// Rust
let template_args = TemplateArgs::evm_wallet_filter(&EvmWalletFilterTemplate {
wallets: vec!["0xnewwallet".to_string()],
})?;
let params = UpdateWebhookTemplateParams {
name: None,
notification_email: None,
destination_attributes: None,
template_args,
};
let webhook = qn.webhooks.update_webhook_template("wh-1", ¶ms).await?;
# Python
webhook = await qn.webhooks.update_webhook_template(
"wh-1",
template_args=TemplateArgs.evm_wallet_filter(
EvmWalletFilterTemplate(wallets=["0xnewwallet"])
),
)
// Node.js
const webhook = await qn.webhooks.updateWebhookTemplate("wh-1", {
templateArgs: TemplateArgs.evmWalletFilter({ wallets: ["0xnewwallet"] }),
});
# Ruby
template_args = JSON.generate({
template_id: "evmWalletFilter",
value: JSON.generate({ wallets: ["0xnewwallet"] })
})
webhook = JSON.parse(qn.webhooks.update_webhook_template(
webhook_id: "wh-1",
template_args_json: template_args
))
delete_webhook / deleteWebhook
Deletes a webhook.
Parameters: id (required).
Returns: nothing.
// Rust
qn.webhooks.delete_webhook("wh-1").await?;
# Python
await qn.webhooks.delete_webhook("wh-1")
// Node.js
await qn.webhooks.deleteWebhook("wh-1");
# Ruby
qn.webhooks.delete_webhook(id: "wh-1")
delete_all_webhooks / deleteAllWebhooks
Deletes every webhook on the account. Destructive and takes no arguments.
Parameters: none.
Returns: nothing.
// Rust
qn.webhooks.delete_all_webhooks().await?;
# Python
await qn.webhooks.delete_all_webhooks()
// Node.js
await qn.webhooks.deleteAllWebhooks();
# Ruby
qn.webhooks.delete_all_webhooks
pause_webhook / pauseWebhook
Pauses a webhook so it stops delivering events.
Parameters: id (required).
Returns: nothing.
// Rust
qn.webhooks.pause_webhook("wh-1").await?;
# Python
await qn.webhooks.pause_webhook("wh-1")
// Node.js
await qn.webhooks.pauseWebhook("wh-1");
# Ruby
qn.webhooks.pause_webhook(id: "wh-1")
activate_webhook / activateWebhook
Activates a paused or new webhook so it resumes delivering events. start_from determines where processing resumes.
Parameters: id (required), start_from (WebhookStartFrom, required — Last or Latest).
Returns: nothing.
// Rust
let params = ActivateWebhookParams { start_from: WebhookStartFrom::Latest };
qn.webhooks.activate_webhook("wh-1", ¶ms).await?;
# Python
await qn.webhooks.activate_webhook("wh-1", start_from="latest")
// Node.js
import { WebhookStartFrom } from "quicknode-sdk";
await qn.webhooks.activateWebhook("wh-1", { startFrom: WebhookStartFrom.Latest });
# Ruby
qn.webhooks.activate_webhook(id: "wh-1", start_from: "latest")
get_enabled_count / getEnabledCount
Counts currently enabled webhooks.
Parameters: none.
Returns: WebhookEnabledCountResponse with total.
// Rust
let resp = qn.webhooks.get_enabled_count().await?;
# Python
resp = await qn.webhooks.get_enabled_count()
// Node.js
const resp = await qn.webhooks.getEnabledCount();
# Ruby
resp = JSON.parse(qn.webhooks.get_enabled_count)
KV Store Client
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/.
Sets
create_set / createSet
Stores a single string value under a key.
Parameters: key (string, required), value (string, required).
Returns: nothing.
// Rust
qn.kvstore.create_set(&CreateSetParams {
key: "my-key".to_string(),
value: "hello".to_string(),
}).await?;
# Python
await qn.kvstore.create_set(key="my-key", value="hello")
// Node.js
await qn.kvstore.createSet({ key: "my-key", value: "hello" });
# Ruby
qn.kvstore.create_set(key: "my-key", value: "hello")
get_sets / getSets
Paginated page of key/value entries.
Parameters (all optional): limit (i64), cursor (string).
Returns: GetSetsResponse — { data: KvSetEntry[], cursor: string }.
// Rust
let resp = qn.kvstore.get_sets(&Default::default()).await?;
# Python
resp = await qn.kvstore.get_sets()
// Node.js
const resp = await qn.kvstore.getSets();
# Ruby
resp = JSON.parse(qn.kvstore.get_sets({}))
get_set / getSet
Returns the value stored under a key.
Parameters: key (string, required).
Returns: GetSetResponse with value.
// Rust
let resp = qn.kvstore.get_set("my-key").await?;
# Python
resp = await qn.kvstore.get_set("my-key")
// Node.js
const resp = await qn.kvstore.getSet("my-key");
# Ruby
resp = JSON.parse(qn.kvstore.get_set(key: "my-key"))
bulk_sets / bulkSets
Adds and/or deletes multiple sets in a single request.
Parameters (at least one required): add_sets (map<string,string>, optional), delete_sets (string[], optional).
Returns: nothing.
// Rust
use std::collections::HashMap;
let mut add_sets = HashMap::new();
add_sets.insert("k1".to_string(), "v1".to_string());
qn.kvstore.bulk_sets(&BulkSetsParams {
add_sets: Some(add_sets),
delete_sets: Some(vec!["old-key".to_string()]),
}).await?;
# Python
await qn.kvstore.bulk_sets(
add_sets={"k1": "v1"},
delete_sets=["old-key"],
)
// Node.js
await qn.kvstore.bulkSets({
addSets: { k1: "v1" },
deleteSets: ["old-key"],
});
# Ruby
qn.kvstore.bulk_sets(add_sets: { "k1" => "v1" }, delete_sets: ["old-key"])
delete_set / deleteSet
Deletes a single set.
Parameters: key (string, required).
Returns: nothing.
// Rust
qn.kvstore.delete_set("my-key").await?;
# Python
await qn.kvstore.delete_set("my-key")
// Node.js
await qn.kvstore.deleteSet("my-key");
# Ruby
qn.kvstore.delete_set(key: "my-key")
Lists
create_list / createList
Creates a list under a key, seeded with the initial items.
Parameters: key (string, required), items (string[], required).
Returns: nothing.
// Rust
qn.kvstore.create_list(&CreateListParams {
key: "my-list".to_string(),
items: vec!["0xabc".to_string(), "0xdef".to_string()],
}).await?;
# Python
await qn.kvstore.create_list(key="my-list", items=["0xabc", "0xdef"])
// Node.js
await qn.kvstore.createList({ key: "my-list", items: ["0xabc", "0xdef"] });
# Ruby
qn.kvstore.create_list(key: "my-list", items: ["0xabc", "0xdef"])
get_lists / getLists
Paginated page of list keys.
Parameters (all optional): limit (i64), cursor (string).
Returns: GetListsResponse — { data: { keys: string[] }, cursor: string }.
// Rust
let resp = qn.kvstore.get_lists(&Default::default()).await?;
# Python
resp = await qn.kvstore.get_lists()
// Node.js
const resp = await qn.kvstore.getLists();
# Ruby
resp = JSON.parse(qn.kvstore.get_lists({}))
get_list / getList
Paginated page of items for a specific list.
Parameters: key (string, required); optional limit (i64), cursor (string).
Returns: GetListResponse — { data: { items: string[] }, cursor: string }.
// Rust
let resp = qn.kvstore.get_list("my-list", &Default::default()).await?;
# Python
resp = await qn.kvstore.get_list("my-list")
// Node.js
const resp = await qn.kvstore.getList("my-list");
# Ruby
resp = JSON.parse(qn.kvstore.get_list(key: "my-list"))
update_list / updateList
Adds and/or removes items in a single operation.
Parameters: key (string, required); optional: add_items (string[]), remove_items (string[]).
Returns: nothing.
// Rust
qn.kvstore.update_list(
"my-list",
&UpdateListParams {
add_items: Some(vec!["0x456".to_string()]),
remove_items: Some(vec!["0xabc".to_string()]),
},
).await?;
# Python
await qn.kvstore.update_list(
"my-list",
add_items=["0x456"],
remove_items=["0xabc"],
)
// Node.js
await qn.kvstore.updateList("my-list", {
addItems: ["0x456"],
removeItems: ["0xabc"],
});
# Ruby
qn.kvstore.update_list(key: "my-list", add_items: ["0x456"], remove_items: ["0xabc"])
add_list_item / addListItem
Appends a single item to a list.
Parameters: key (string, required), item (string, required).
Returns: nothing.
// Rust
qn.kvstore.add_list_item(
"my-list",
&AddListItemParams { item: "0x123".to_string() },
).await?;
# Python
await qn.kvstore.add_list_item("my-list", "0x123")
// Node.js
await qn.kvstore.addListItem("my-list", { item: "0x123" });
# Ruby
qn.kvstore.add_list_item(key: "my-list", item: "0x123")
list_contains_item / listContainsItem
Checks whether a list contains a specific item.
Parameters: key (string, required), item (string, required).
Returns: ListContainsItemResponse with exists: bool.
// Rust
let resp = qn.kvstore.list_contains_item("my-list", "0x123").await?;
# Python
resp = await qn.kvstore.list_contains_item("my-list", "0x123")
// Node.js
const resp = await qn.kvstore.listContainsItem("my-list", "0x123");
# Ruby
resp = JSON.parse(qn.kvstore.list_contains_item(key: "my-list", item: "0x123"))
delete_list_item / deleteListItem
Removes a single item from a list.
Parameters: key (string, required), item (string, required).
Returns: nothing.
// Rust
qn.kvstore.delete_list_item("my-list", "0x123").await?;
# Python
await qn.kvstore.delete_list_item("my-list", "0x123")
// Node.js
await qn.kvstore.deleteListItem("my-list", "0x123");
# Ruby
qn.kvstore.delete_list_item(key: "my-list", item: "0x123")
delete_list / deleteList
Deletes a list and all of its items.
Parameters: key (string, required).
Returns: nothing.
// Rust
qn.kvstore.delete_list("my-list").await?;
# Python
await qn.kvstore.delete_list("my-list")
// Node.js
await qn.kvstore.deleteList("my-list");
# Ruby
qn.kvstore.delete_list(key: "my-list")
Error Handling
Every binding exposes a typed exception hierarchy derived from the core SdkError
enum (crates/core/src/errors.rs). Catch the base class (QuickNodeError /
QuickNodeSdk::Error / SdkError) for any SDK-originated failure, or a specific
subclass to branch on transport vs. API semantics.
| Logical class | When it fires | Extra fields |
|---|---|---|
QuickNodeError |
base class; catches everything below | — |
ConfigError |
invalid config or URL surfaced at construction time | — |
HttpError |
transport failure that isn't a timeout/connect | — |
TimeoutError |
request timed out (subclass of HttpError) |
— |
ConnectionError |
connection refused / DNS / TLS (subclass of HttpError) |
— |
ApiError |
non-2xx HTTP response | status, body |
DecodeError |
2xx response but JSON parse failed | body |
Per-language names:
- Rust — pattern-match on
SdkError { Http, Api, Decode, UrlParse, Config }; useerr.http_kind()to classifyHttpintoTimeout,Connect, orOther. - Python —
QuickNodeError,ConfigError,HttpError,TimeoutError,ConnectionError,ApiError,DecodeError(importable fromsdk). - Node.js — same class names, importable from
@quicknode/sdk, all extendError. - Ruby —
QuickNodeSdk::Error,QuickNodeSdk::ConfigError,QuickNodeSdk::HttpError,QuickNodeSdk::TimeoutError,QuickNodeSdk::ConnectionError,QuickNodeSdk::ApiError,QuickNodeSdk::DecodeError; all extendStandardError. Hash-key validation still raisesArgumentError.
// Rust
match qn.admin.show_endpoint("missing").await {
Ok(resp) => println!("{:?}", resp.data),
Err(SdkError::Api { status, body }) if status.as_u16() == 404 => {
eprintln!("not found: {body}")
}
Err(e) if matches!(e.http_kind(), Some(HttpKind::Timeout)) => eprintln!("timed out"),
Err(e) => eprintln!("other: {e}"),
}
# Python
from sdk import ApiError, TimeoutError
try:
await qn.admin.show_endpoint("missing")
except ApiError as e:
if e.status == 404:
print(f"not found: {e.body}")
else:
raise
except TimeoutError:
print("timed out")
// Node.js
import { ApiError, TimeoutError } from "@quicknode/sdk";
try {
await qn.admin.showEndpoint("missing");
} catch (e) {
if (e instanceof ApiError && e.status === 404) console.error("not found:", e.body);
else if (e instanceof TimeoutError) console.error("timed out");
else throw e;
}
# Ruby
begin
qn.admin.show_endpoint(id: "missing")
rescue QuickNodeSdk::ApiError => e
warn "api #{e.status}: #{e.body}" if e.status == 404
rescue QuickNodeSdk::TimeoutError
warn "timed out"
end
Development
Prerequisites
Build Commands
Use the commands in the Justfile for the setup and build commands.
# Core library
cargo check
cargo test -p quicknode-sdk
# Python (from project root)
just python-setup-env
just python-build
# Node.js (from npm/)
just node-build
# Ruby
just ruby-build
# Rust
cargo build -p quicknode-sdk
Testing
just test
Runs the Rust unit tests for quicknode-sdk using wiremock to mock HTTP responses — no API key required.
Examples
# Rust
QN_SDK__API_KEY=replaceme cargo run --example admin -p quicknode-sdk --features rust
# Python
QN_SDK__API_KEY=replaceme uv run python/examples/admin.py
QN_SDK__API_KEY=replaceme uv run python/examples/streams.py
# Node.js
cd npm && QN_SDK__API_KEY=replaceme npx tsx examples/admin.ts
cd npm && QN_SDK__API_KEY=replaceme npx tsx examples/streams.ts
# Ruby (build first, then run)
just ruby-build
QN_SDK__API_KEY=replaceme ruby ruby/examples/admin.rb
QN_SDK__API_KEY=replaceme ruby ruby/examples/admin_e2e.rb
QN_SDK__API_KEY=replaceme ruby ruby/examples/streams.rb
Releasing
The Rust crate (quicknode-sdk on crates.io) versions independently from the Python, Node, and Ruby bindings. Its version lives in crates/core/Cargo.toml; the bindings share the workspace version in the root Cargo.toml.
Rust crate only (crates.io)
# 1. Bump the version in crates/core/Cargo.toml (e.g. 0.1.0 → 0.1.0-alpha.5)
# Pre-release identifiers use SemVer 2.0 syntax: MAJOR.MINOR.PATCH-<id>.<N>
# Examples: 0.1.0-alpha.4, 0.2.0-beta.1, 0.2.0-rc.1
# 2. Commit and push
git commit -am "chore: release quicknode-sdk 0.1.0-alpha.5"
git push
# 3. Validate the tarball (no upload)
cargo publish -p quicknode-sdk --dry-run
# 4. Publish (requires `cargo login` with a crates.io token)
cargo publish -p quicknode-sdk
The first publish claims the quicknode-sdk name permanently. Published versions are immutable — you cannot overwrite or delete them (only cargo yank, which hides but doesn't remove).
All bindings together (Python / Node / Ruby)
macOS (Apple Silicon) artifacts are built locally rather than on GitHub Actions to avoid the ~10× runner cost. Linux artifacts are built by CI when a GitHub release is published.
-
Bump versions and commit:
just release 0.2.0 git push
-
Create the GitHub release via the GitHub UI:
- Releases → Draft a new release.
- Choose a tag → type
v0.2.0→ Create new tag on publish. - Target branch:
main. - Fill in title and notes (or click Generate release notes).
- Click Publish release.
This creates + pushes the tag and triggers
.github/workflows/release.yml, which builds Linux artifacts and attaches them to the release. -
Build macOS arm64 artifacts locally and append them to the release:
just macos-build-and-publish 0.2.0
Step 3 requires the gh CLI authenticated to the repo. Intel macOS (x86_64-apple-darwin) is not shipped — users on Intel Macs install from source.
just release does not bump the Rust crate version (that's managed separately in crates/core/Cargo.toml). If you want the Rust crate to move in lockstep with a binding release, bump it manually in the same commit.
npm publish (@quicknode/sdk)
The Node package is published to npm as @quicknode/sdk. During the 3.x pre-release period, publishes use the next dist-tag so npm install @quicknode/sdk continues to resolve to the legacy 2.x release while npm install @quicknode/sdk@next pulls the rewrite.
The npm publish uses napi-rs's multi-package layout: one main package plus per-platform sub-packages (@quicknode/sdk-linux-x64-gnu, @quicknode/sdk-darwin-arm64, etc.) declared as optionalDependencies. Publishing is triggered manually via a GitHub Actions workflow so the macOS binary (built locally) can be uploaded to the GitHub release before publish.
Anyone with permission to run the Publish npm workflow in this repo can cut a release.
Note on versions: the git tag tracks the overall project version (e.g. v0.1.0-alpha.5) and is set in crates/core/Cargo.toml / the root Cargo.toml. The npm package version is set independently in npm/package.json (e.g. 3.0.0-alpha.5) to stay compatible with the pre-existing @quicknode/sdk 2.x series on npm. The two versions do not need to match.
Per-release flow:
-
Bump the npm version in
npm/package.json(e.g.3.0.0-alpha.4→3.0.0-alpha.5), commit, and push tomain. (Bump the overall project version injust release <version>as part of the normal release flow above — this sets the git tag.) -
Create the GitHub release via the GitHub UI:
- Go to Releases → Draft a new release.
- Click Choose a tag, type the new tag (e.g.
v0.1.0-alpha.5), and select Create new tag on publish. - Target branch:
main. - Fill in the title and release notes (or click Generate release notes).
- Click Publish release.
Publishing the release creates + pushes the tag, which triggers
.github/workflows/release.yml. CI builds the Linux.nodeartifacts and attaches them to the release you just created. -
Wait for
release.ymlto finish. Confirm the four Linuxindex.*.nodeartifacts are attached to the release. -
Build and upload the macOS arm64 binary locally (Apple Silicon Mac required):
just node-build gh release upload v0.1.0-alpha.5 npm/index.darwin-arm64.node
-
Trigger the publish workflow. From the GitHub UI: Actions → Publish npm → Run workflow, then enter the git tag (
v0.1.0-alpha.5) and npm dist-tag (next). Or via CLI:gh workflow run publish-npm.yml -f tag=v0.1.0-alpha.5 -f npm_tag=next
-
Verify.
npm view @quicknode/sdk dist-tags # Expected: next: 3.0.0-alpha.5, latest: 2.6.0 (unchanged)
Users can install the pre-release with npm install @quicknode/sdk@next.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quicknode_sdk-0.1.0a6-cp314-cp314-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp314-cp314-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.14, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
556642e3589f2a14dc7f3a699fc7f32953f5241c4d94397fc4a5357f230f2b14
|
|
| MD5 |
6702eb4c61c18829511f9db74294165c
|
|
| BLAKE2b-256 |
b0f734357ef2759ccbe15ef0664d18533495a3c88cd68c18f77cb4f8004a43c3
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp314-cp314-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp314-cp314-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.14, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b84ad1eb7ba40d233f20a08bf79eb07dd3640ed4dc1e05276a32355f83610a5
|
|
| MD5 |
526fe78dc02bae197e1b2c72261e6f47
|
|
| BLAKE2b-256 |
860cdbbe2d6140aa78822a223f4d3731908e0838bc0ab9586ead1fc110cac099
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp314-cp314-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp314-cp314-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.14, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1722ebd409cdbbe9a6d2a06a87d517b7b4a2482fdc1f5057d3cae618e980c3f6
|
|
| MD5 |
446e537797dfdf42857becaf502fb6df
|
|
| BLAKE2b-256 |
aa3b1adaa8d52d47a0aebd38e6013d44738a3ccd85b230400b6842f1e03f7c0d
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69938b7b5e0d920192a172d177e13eb0fb55301a51205daf56bbae6b6cf0bbe5
|
|
| MD5 |
684c56cfcc343a1871e00944ef491207
|
|
| BLAKE2b-256 |
f16876661122ccaa24d04c02504d273a62f5a35a344d26e964c340f022199480
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp314-cp314-macosx_11_0_arm64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp314-cp314-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.5 MB
- Tags: CPython 3.14, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a2a0b545b22d10e069578faeee404455dc757a2eeac6bd0e80f0a5619588883
|
|
| MD5 |
a0a22ab8fe5036eacb7080ced68ab881
|
|
| BLAKE2b-256 |
b885b1e65863c0410ab02134993207d05be1972e8da082496565cbd723ee3065
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp313-cp313-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp313-cp313-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.13, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b45d11e54f345b9895481f0e8800804899cc561c661183c3285e1c66a644e2bf
|
|
| MD5 |
ad3451ebea05dbb7f6ffef9a126c9fee
|
|
| BLAKE2b-256 |
4a3b9d925dc98569c47c0ad6601f4f8f6b7003bc02ba47007538795bd12a8207
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp313-cp313-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp313-cp313-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.13, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bc1a757d31db53f0a956f97326e435cdc2f78ef4228027ba72029520769f58c
|
|
| MD5 |
6e31eb74feee9718a723251a3e3a390d
|
|
| BLAKE2b-256 |
a31ec8e3e42e03add341b506b7635bcc0112517ef03b664e2cd8f01d4fb9a699
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp313-cp313-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp313-cp313-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.13, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70c8c1d37cf424652611720b94afb71b512b9914db6521f60bb9cf31651828be
|
|
| MD5 |
3dbb51ee9892be1f6fcc807a46b45d2b
|
|
| BLAKE2b-256 |
683cfce12ab92e75785716266a139a0a362bc6a039aade18e2bbcaec6c39b940
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e70bfcc8a5cd69210802495d4604ca24222c2fc7a13cfa830820df9f243b93c
|
|
| MD5 |
166633bfa0a52a0e06783b41e9d1d10f
|
|
| BLAKE2b-256 |
2458b7969cfd24f131b5d99d7a8a6e6bd63c28e2ce2ac3ab538fc6b7eef721ee
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.5 MB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
762f8441e7dda2bceeae8ed7961197089d27de8f91466f118a9fd6d6fa5375f5
|
|
| MD5 |
b5b932edb175fb77558346ac9809b186
|
|
| BLAKE2b-256 |
41d2c4495fc2c4f0a8089cd47568f91b1b5fbdb89140ea33153a50673c11da0c
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp312-cp312-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp312-cp312-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.12, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65983df0c139bad8cdba6c37f69b91c1752f234954c1518477c07f07295d0a4a
|
|
| MD5 |
b677c09b71b1014b2bbbd77e6e72e5a5
|
|
| BLAKE2b-256 |
7f07fa68b79771b360436d2320ed492f11b043ab947517009db7508d9f43236a
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp312-cp312-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp312-cp312-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.12, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4a09c62e80a2a4267f10978928d78fbab2cfeb32433ec667d0e966fdd7de24b
|
|
| MD5 |
5bdad2d270808f8196649ee406d16c26
|
|
| BLAKE2b-256 |
7f1c3000a9e2345ecbb03b5785a730a79f4721fcedc084958b63f017e21ab501
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp312-cp312-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp312-cp312-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.12, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
287409cdad1e74a68cd89ce6f558e629da07d4ee7f5fde616fb80c8c751358c9
|
|
| MD5 |
d34e0447cb5159040e145b06157323d1
|
|
| BLAKE2b-256 |
c445932c6e83d8534c91cfa4159088ae066481e4a2f2c3fe3268c5ee5be8d212
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eaa2dc04db726ed51ccc37003b4e9646ede70274b68f1192fb0c6e0f5fe8c809
|
|
| MD5 |
ee573d8540aaed0e4ed6d4be9208e223
|
|
| BLAKE2b-256 |
c7bd2f0117e4b2896834bae10709d345c1ff878fe434e3eea5832b99f82ba1a8
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.5 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0541d522810ad14bccacc56685c977c4cbb5b7d7c29a8fccb75cc0257f605f36
|
|
| MD5 |
b820006b434c338c4181fb88f344f866
|
|
| BLAKE2b-256 |
e66ec3a6a5e1ff4dcdd6ec5368d3366f6299a4e5cc1e236a6f6ccc976cc6c1bc
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp311-cp311-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp311-cp311-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.11, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1677c20bd415fd02cae9daae666e0939b55752974b6bbf5fa8b9f734512c92a9
|
|
| MD5 |
7d19867dc6df26abb3ad855e29154205
|
|
| BLAKE2b-256 |
e77e1c6dac3b3f0f8646e107b2090b95d7c116c259235524a5d3c0291752cb39
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp311-cp311-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp311-cp311-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.11, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0607c9dbb4d6f543899c0ee5226fd05bc8db6ef085e61593494f6628cb7255b
|
|
| MD5 |
679faa2c84a7d738e272fa94b5f00812
|
|
| BLAKE2b-256 |
cf3bb16f0013ce4ab747a23e869c55f7d309080582231a92fd262852bcdf0d9b
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp311-cp311-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp311-cp311-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: CPython 3.11, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b2b55282187089dce18113381051ff89efc359f9df5e7424d4f651c65326aae
|
|
| MD5 |
ca9ba7401e1a225c5529a2b4b799a724
|
|
| BLAKE2b-256 |
0799d5e1b643d314f63471d7e19f757c0d848b6d501e467c11ca458e8de637bf
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad24f9b94168302a473f41869de70c5cdd2125edfd3f85273250d50e65a91189
|
|
| MD5 |
611629f3af7b1e444c5ae4b085838198
|
|
| BLAKE2b-256 |
7362471e48faabc71aad8a6d7e3288078d933277bb0aecd9dc892f522e3417be
|
File details
Details for the file quicknode_sdk-0.1.0a6-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: quicknode_sdk-0.1.0a6-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.5 MB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b61dfb4dcb32efb9b5be5f00bfdd6f74dc720fe041ab6c54bde5610d050c6c3
|
|
| MD5 |
5dafe8a0e81215fde9a5873b6a32b898
|
|
| BLAKE2b-256 |
1185e9df81984dab5af2998a4140bb59097d9b504a8e3297bf6d8c96c7b95af5
|