Expand description
§Paykit Library
Stateless Rust crate that implements Paykit Library functionality on Pubky. It provides helpers for public Payment Endpoints (stored as plaintext files on the homeserver), Private Payment Lists, Payment Requests, Allowances, Encrypted Links, and Receipts, while delegating Pubky authentication and session management to callers.
Pubky is the only supported network/storage backend for this crate, and Pubky dependencies are unconditional.
§Quick Start
Add paykit-lib to your Cargo.toml.
[dependencies]
paykit-lib = "0.1.0"
pubky = "0.16.2"The caller supplies an authenticated pubky::PubkySession, a
pubky::PublicStorage handle, and the payee’s public key. Session creation,
capability scope, and key rotation remain the caller’s responsibility.
Minimal example: store and retrieve a public Payment Endpoint.
use paykit_lib::{
set_payment_endpoint, get_payment_endpoint, get_payment_list,
PaykitAppId, PaymentEndpointIdentifier, PaymentEndpointPayload,
};
// Create validated types.
let app_id = PaykitAppId::new("bitkit")?;
let identifier = PaymentEndpointIdentifier::new("btc-lightning-bolt11")?;
let payload = PaymentEndpointPayload::new("lnbc1...");
// Store a Payment Endpoint using an authenticated PubkySession.
set_payment_endpoint(&session, &app_id, identifier.clone(), payload).await?;
// Read it back using pubky::PublicStorage.
if let Some(endpoint) = get_payment_endpoint(&public_storage, &payee_pubkey, &app_id, &identifier).await? {
println!("{}", endpoint.as_str());
}
// List all Payment Endpoints published by this app for a payee.
let payment_list = get_payment_list(&public_storage, &payee_pubkey, &app_id).await?;
for (identifier, payload) in &payment_list.payment_endpoints {
println!("{}: {}", identifier.as_str(), payload.as_str());
}§Core Types
Payment Request domain values use validated construction and read-only accessors. See the Rust migration guide for replacing struct literals and field mutation.
§PaymentEndpointIdentifier
Machine-readable identifier for a Payment Endpoint type (for example "btc-bitcoin-p2tr" or "btc-lightning-bolt11").
PaymentEndpointIdentifier is validated at construction time to prevent path injection attacks.
use paykit_lib::PaymentEndpointIdentifier;
// Construction is fallible:
let identifier = PaymentEndpointIdentifier::new("btc-lightning-bolt11").unwrap();
assert_eq!(identifier.as_str(), "btc-lightning-bolt11");
// Path traversal is rejected:
assert!(PaymentEndpointIdentifier::new("../etc/passwd").is_err());Allowed values: 1-64 ASCII characters from the set [a-zA-Z0-9_-.]. The value must not consist solely of dots (. and .. are rejected as path traversal components), and private is reserved for Paykit storage. Slashes, null bytes, spaces, and other special characters are rejected.
PaymentEndpointIdentifier::new() returns Err(PaykitError::Validation(...)) for invalid input.
Read access is available via as_str(), Display, and AsRef<str>.
Naming convention: PaymentEndpointIdentifier values are opaque to the library, but counterparties need to agree on them to interoperate. A recommended (non-obligatory) convention for the shape of these identifiers is described in ../specs/payment-endpoint-identifier.md.
§PaymentEndpointPayload
Serialized Payment Endpoint Payload (UTF-8 text such as JSON, lnurl, etc.).
use paykit_lib::PaymentEndpointPayload;
let payload = PaymentEndpointPayload::new("ln...");
let payload_str: &str = payload.as_str();
let owned: String = payload.into_inner();§PaymentList
Collection of Payment Endpoints keyed by Payment Endpoint Identifiers. Returned by get_payment_list.
use paykit_lib::{PaykitAppId, PaymentList};
let app_id = PaykitAppId::new("bitkit")?;
let payment_list: PaymentList = get_payment_list(&public_storage, &payee, &app_id).await?;
// Access the underlying map:
for (identifier, payload) in &payment_list.payment_endpoints {
println!(
"identifier={} payload={}",
identifier.as_str(),
payload.as_str()
);
}
// Check if empty:
if payment_list.payment_endpoints.is_empty() {
println!("no Payment Endpoints published");
}Private Payment Lists use a versioned PrivatePaymentList value. The Payment Endpoints still use the same HashMap<PaymentEndpointIdentifier, PaymentEndpointPayload> layout. Payment-specific correlation belongs in Payment Requests, Payment Proofs, and Receipts, not in endpoint publication:
use paykit_lib::{parse_private_payment_list_json, PrivateMessageKind};
let messages = link.receive_private_application_messages().await?;
for message in messages {
if message.known_kind() == Some(PrivateMessageKind::PrivatePaymentList) {
let list = parse_private_payment_list_json(&message.raw_json)?;
for (identifier, payload) in &list.payment_endpoints {
println!(
"identifier={} payload={}",
identifier.as_str(),
payload.as_str()
);
}
}
}Private Payment Lists use Latest-State Message semantics per Paykit App at the SDK/runtime layer: if one app queues several list messages, its latest valid list supersedes its older list messages without replacing lists from other apps. Malformed newer list messages do not supersede the latest valid state. Receipt Access, Allowance, and Payment Request messages use Event Message semantics, so SDK/runtime code must preserve every valid message in send order.
The payment_endpoints field is a HashMap<PaymentEndpointIdentifier, PaymentEndpointPayload>.
§Paykit Apps And App Registry
PaykitAppId identifies the app that owns a public Payment Endpoint or sent a
private message. PaykitAppRegistry is one public identity-wide record at
/pub/paykit/v0/app-registry.json; it lists participating apps, their coarse
capabilities, the current identity-wide Noise public key and key generation,
and optional default-app preferences. It is not private SDK state.
The registry does not authorize its Noise key. The identity signs a
PaykitNoiseKeyAuthorization at /pub/paykit-authority/v0/current-key.json,
outside /pub/paykit/:rw. get_paykit_noise_key_authorization verifies the
signature and expected owner. Low-level callers must retain peer pins and match
routing keys and remote_static_public_key() to the signed record before using
new or restored links; follow the SDK’s checks
and trust model. Publishing requires
separate authority-path write access.
Registries are bounded to 64 KiB, 64 applications, and 256 endpoint-specific defaults so remote data cannot trigger unbounded parsing or endpoint lookups.
Public Payment Endpoints are stored under
/pub/paykit/v0/apps/{app_id}/endpoints/. Private Paykit messages share one
identity-wide Encrypted Link per counterparty and include app_id in their
versioned JSON.
§PaykitError
Domain error enum with the following variants:
| Variant | Meaning |
|---|---|
Transport { context, source } | Network or Pubky SDK failure |
NotFound(String) | Requested resource does not exist (404/GONE) |
InvalidData { context, source } | Fetched data is corrupt or structurally invalid |
Validation(String) | Caller-supplied input failed validation (e.g. invalid PaymentEndpointIdentifier) |
The source field on Transport and InvalidData is backed by anyhow::Error so callers can downcast via anyhow::Error::downcast_ref when they need the original typed error.
§Result<T>
All public APIs return paykit_lib::Result<T>, which is an alias for std::result::Result<T, PaykitError>.
§Pubky Sessions and I/O
- Public Payment Endpoints use concrete Pubky SDK handles. Writes take
&pubky::PubkySession; reads take&pubky::PublicStorage. - Private Payment Lists use
pubky-noise’sPubkyNoiseEncryptorfor Noise-encrypted messaging, which handles both encryption and homeserver I/O through Pubky. Private Payment List functions accept anEncryptedLinkestablished via an Encrypted Link Handshake. - Paykit stays stateless. Session creation, capability scoping, key rotation, account recovery, and client timeout configuration remain caller responsibilities.
- Public payment paths are centralized by
PAYKIT_PATH_PREFIX(/pub/paykit/v0/, including the trailing slash). Private Paykit message paths usePAYKIT_PRIVATE_PATH_PREFIX(/pub/paykit/v0/private) as the base for pubky-noise path derivation.
§Timeout Handling
Paykit does not wrap Pubky SDK calls with its own deadline. A slow or unresponsive homeserver can block the caller unless the Pubky client is configured with appropriate timeouts. The Pubky SDK exposes PubkyHttpClientBuilder::request_timeout:
use std::time::Duration;
let client = PubkyHttpClient::builder()
.request_timeout(Duration::from_secs(10))
.build()?;§API Surface
§Public Payment Endpoints
These functions operate on concrete Pubky SDK handles.
§set_payment_endpoint
Store or update a payee-owned Payment Endpoint using the caller’s authenticated pubky::PubkySession.
use paykit_lib::{set_payment_endpoint, PaykitAppId, PaymentEndpointIdentifier, PaymentEndpointPayload};
async fn demo(session: &pubky::PubkySession) -> paykit_lib::Result<()> {
// NOTE: parties need to agree on Payment Endpoint Identifiers to interoperate.
let app_id = PaykitAppId::new("bitkit")?;
let identifier = PaymentEndpointIdentifier::new("btc-lightning-bolt11")?;
let payload = PaymentEndpointPayload::new("ln...");
set_payment_endpoint(session, &app_id, identifier, payload).await?;
let identifier = PaymentEndpointIdentifier::new("btc-bitcoin-p2wpkh")?;
let payload = PaymentEndpointPayload::new("bc1...");
set_payment_endpoint(session, &app_id, identifier, payload).await?;
// or
let identifier = PaymentEndpointIdentifier::new("btc-bitcoin-p2tr")?;
let payload = PaymentEndpointPayload::new("bc1...");
set_payment_endpoint(session, &app_id, identifier, payload).await?;
Ok(())
}§remove_payment_endpoint
Remove a previously published Payment Endpoint Payload for a given Payment Endpoint Identifier.
use paykit_lib::{remove_payment_endpoint, PaykitAppId, PaymentEndpointIdentifier};
async fn demo(session: &pubky::PubkySession) -> paykit_lib::Result<()> {
let app_id = PaykitAppId::new("bitkit")?;
let identifier = PaymentEndpointIdentifier::new("btc-lightning-bolt11")?;
remove_payment_endpoint(session, &app_id, identifier).await?;
Ok(())
}Note: Removing a non-existent Payment Endpoint succeeds, so cleanup can be retried safely.
§get_payment_list
Fetch the public Payment List for a public key. The result is empty when no Payment Endpoints are published.
use paykit_lib::{get_payment_list, PaykitAppId, PublicKey};
async fn demo(public_storage: &pubky::PublicStorage, pk: &PublicKey) -> paykit_lib::Result<()> {
let app_id = PaykitAppId::new("bitkit")?;
let payment_list = get_payment_list(public_storage, pk, &app_id).await?;
if payment_list.payment_endpoints.is_empty() {
println!("payee published no Payment Endpoints yet");
} else {
for (identifier, payload) in &payment_list.payment_endpoints {
println!(
"identifier={} payload={}",
identifier.as_str(),
payload.as_str()
);
}
}
Ok(())
}§get_payment_endpoint
Convenience resolver for a single Payment Endpoint Identifier. Returns Ok(None) when the Payment Endpoint Payload is missing or empty.
use paykit_lib::{get_payment_endpoint, PaykitAppId, PaymentEndpointIdentifier, PublicKey};
async fn inspect(public_storage: &pubky::PublicStorage, pk: &PublicKey) -> paykit_lib::Result<()> {
let app_id = PaykitAppId::new("bitkit")?;
let bolt11 = PaymentEndpointIdentifier::new("btc-lightning-bolt11")?;
if let Some(endpoint) = get_payment_endpoint(public_storage, pk, &app_id, &bolt11).await? {
println!("bolt11 payload: {}", endpoint.as_str());
} else {
println!("no bolt11 Payment Endpoint published");
}
Ok(())
}§Consistency Note
get_payment_list first lists available Payment Endpoints and then fetches each one individually. Because Pubky public storage does not support atomic reads, a race condition exists: between the directory listing and the individual fetches, endpoints may be added, removed, or modified by the payee. The returned PaymentList is therefore a best-effort snapshot.
If a payment execution fails with an error suggesting the endpoint has been consumed or is no longer valid, callers should:
- Re-fetch the specific app-owned endpoint via
get_payment_endpoint. - Compare the newly retrieved
PaymentEndpointPayloadwith the value used in the failed attempt. - If the Payment Endpoint Payload differs, retry the payment with the updated value.
§Private Payment Lists
Private Payment Lists are end-to-end encrypted via a Noise protocol handshake managed by pubky-noise. PubkyNoiseEncryptor handles encryption, counter-based file naming, and prepared send/receive state transitions.
Storage paths for private Paykit data are derived per-counterparty pair using pubky_noise::path_derivation::derive_asymmetric_paths. Each party writes to a different path than they read from (write_path vs read_path), preventing third parties from enumerating communication relationships. The base prefix is /pub/paykit/v0/private; the derived hex component is appended as a child segment. Within each derived folder, pubky-noise manages individual file slots using a counter-based scheme — Paykit does not control file names or locations for private Paykit data.
The path domain is paykit-path-v0 followed by the two 32-byte Pubky identity
keys in lexicographic byte order. The Noise DH secret remains part of the path
hash. Copying another identity’s advertised Noise key therefore does not share
its stream, while apps under the same identity still share one path pair.
Session-based helpers obtain the local identity from the Pubky session.
§Handshake Initiation
initiate_encrypted_link(session, sender_noise_secret_key, receiver_identity_public_key, receiver_noise_public_key, recovery_context, outbox_client) -> Result<EncryptedLinkHandshake>Initializes a Noise XX handshake as the initiator. Returns a handshake handle to be driven forward withadvance_handshake.accept_encrypted_link(session, receiver_noise_secret_key, sender_identity_public_key, sender_noise_public_key, recovery_context, outbox_client) -> Result<EncryptedLinkHandshake>Initializes a Noise XX handshake as the responder. Returns a handshake handle to be driven forward withadvance_handshake.
EncryptedLinkRecoveryContext contains the local and remote recovery attempt IDs.
Both peers use the same pair in opposite order. Replacement attempts derive
separate stream paths; snapshots preserve the context for restart. The SDK
manages persistent recovery markers and chooses the initiator by comparing Pubky
public keys. Low-level callers must coordinate these roles and IDs themselves.
§Handshake advancing
-
advance_handshake(handshake: EncryptedLinkHandshake) -> std::result::Result<HandshakeProgress, HandshakeAdvanceError>Advances the handshake by one step. ReturnsHandshakeProgress::Pending(handle)when waiting for the counterparty, orHandshakeProgress::Complete(EncryptedLink)when finished. Polling-safe — the caller controls retry timing and timeouts. If a homeserver write fails during the handshake (HomeserverWriteError), the function automatically recovers from a pre-mutation snapshot and returnsPendingso the caller’s polling loop retries transparently. The maximum number of consecutive recovery attempts is configurable viaEncryptedLinkHandshake::set_max_recovery_attempts(default:DEFAULT_MAX_RECOVERY_ATTEMPTS, 3). The recovery-attempt counter resets to zero after every successful step.HTTP/response-body transport read failures remain real errors.
HandshakeAdvanceError::error()borrows the underlyingPaykitError;into_parts()returns that error and an optional boxed handshake. Only an unchanged transport read failure retains the handle, which can be passed back as*handshakeafter the caller decides to retry. Retained state does not imply a transient failure or authorize automatic retries. Malformed packets and other errors carry no retry handle, and Debug never prints retained handshake state.
§Handshake checkpointing / resumption
EncryptedLinkHandshake::snapshot() -> Result<EncryptedLinkHandshakeSnapshot>Captures the current in-progress handshake state. Fails while a prepared transport operation is unacknowledged.EncryptedLinkHandshake::serialize() -> Result<Vec<u8>>Convenience method equivalent toself.snapshot()?.serialize().EncryptedLinkHandshake::config() -> &Arc<PubkyNoiseConfig>Access the shared Noise configuration for in-process handshake restore.EncryptedLinkHandshakeSnapshot::serialize() -> Vec<u8>/EncryptedLinkHandshakeSnapshot::deserialize(bytes: &[u8]) -> Result<EncryptedLinkHandshakeSnapshot>/EncryptedLinkHandshakeSnapshot::recipient() -> &PublicKey/EncryptedLinkHandshakeSnapshot::remote_noise_public_key() -> &PublicKeySnapshot wire format helpers. The versioned handshake envelope retains the Noise session state, counterparty Noise key, recovery context, and at most one bounded pending-publication packet with its exact destination. Persist pending output before publishing it; acknowledge the exact packet before restoring the checkpoint or promoting the link to transport mode.restore_encrypted_link_handshake(session, secret_key, remote_identity_public_key, outbox_client, snapshot) -> Result<EncryptedLinkHandshake>Cross-restart restore for an in-progress handshake.restore_encrypted_link_handshake_from_config(config, remote_identity_public_key, snapshot) -> Result<EncryptedLinkHandshake>In-process restore for an in-progress handshake.
After handshake restore, recovery tuning resets to defaults: recovery_attempts = 0 and max_recovery_attempts = DEFAULT_MAX_RECOVERY_ATTEMPTS.
Snapshot bytes include sensitive key material and must be treated as secrets (store encrypted at rest; never log or expose them).
§Private Payment List exchange
set_private_payment_list(link: &mut EncryptedLink, list: &PrivatePaymentList) -> Result<()>Serializes the complete Private Payment List to JSON, encrypts it, and sends it via the Encrypted Link. The caller is responsible for managing the Payment Endpoints in the Payment List and passing the full map each time inlist.payment_endpoints. The serialized JSON must fit withinPUBKY_NOISE_MSG_LEN(1000 bytes). Transient homeserver write failures are retried automatically up toEncryptedLink::set_max_send_retriestimes (default:DEFAULT_MAX_SEND_RETRIES, 3). Transport-phase homeserver write failures do not corrupt the Noise state, so retries are safe without snapshot-based recovery. Deterministic state, counter, nonce, or encryption errors fail immediately.parse_private_payment_list_json(json: &str) -> Result<PrivatePaymentList>Stateless parser for callers or SDK layers that route messages fromEncryptedLink::receive_private_application_messages.
Durable runtimes should use
EncryptedLink::prepare_private_application_message_json, persist the exact
ciphertext and resulting snapshot together, acknowledge the prepared send, and
then call publish_prepared_private_application_message. On receive, use
prepare_next_private_application_message, persist the plaintext application
result and resulting snapshot together, and only then call
acknowledge_persisted_private_receive. The SDK runtime implements this staged
flow; the direct stateless send helpers remain convenience APIs.
All Private Application Messages share one ordered encrypted stream and carry a
source app_id. Use EncryptedLink::receive_private_application_messages when
a caller or SDK must route private message kinds durably. The raw JSON is
preserved even when parsed version/kind/app_id header fields are missing
or malformed. Callers that perform irreversible side effects after receiving
Event Messages should persist their own app-level handled/unhandled event state
before persisting a snapshot whose read counter has advanced past those
messages.
Private Paykit wire messages are closed-world JSON objects: unknown fields are rejected unless a field is explicitly defined as an open JSON object, such as Payment Request metadata, Payment Proof proof, or Receipt Metadata.
§Payment Request exchange
Payment Requests are payee-initiated private protocol objects exchanged over an Encrypted Link. Their lifecycle messages (paykit.payment_request, acceptance, rejection, cancellation, and proof) use Event Message semantics. Paykit serializes, encrypts, sends, receives, and structurally validates these messages, but does not execute payments, schedule recurring jobs, manage wallet state, validate sender-role intent, or validate payment-method-specific proofs.
An accepted Recurring Payment Request is the protocol object behind a product Subscription; Paykit does not define a separate Subscription protocol or execute its periodic payments. See Recurring Payment Requests And Subscriptions for the complete responsibility split and lifecycle.
send_payment_request(link, app_id, event: &PaymentRequest) -> Result<()>Sends apaykit.payment_requestproposal with immutable terms. Terms includePaymentAmount, a payee-providedPaymentReference, required nullableproposal_expires_at(None/nullmeans no protocol-level proposal expiry before acceptance), optionalRecurrence, accepted Payment Endpoint Identifiers, and optional metadata.serialize_payment_request_event(app_id, event: &PaymentRequestEvent) -> Result<String>Serializes a Payment Request event to the exact JSON payload callers can persist before sending for crash-safe retry/idempotency.parse_payment_request_event_message(message: &PrivateApplicationMessage) -> Option<PaymentRequestEventMessage>Stateless parser for Payment Request events from the raw Private Application Message stream. Recognized but malformed events are returned with a validation error so callers can persist the raw payload before advancing their durable checkpoint.send_payment_request_acceptance(link, app_id, event: &PaymentRequestAcceptance) -> Result<()>Sends an explicit payer acceptance for a proposed Payment Request.send_payment_request_rejection(link, app_id, event: &PaymentRequestRejection) -> Result<()>Sends a payer rejection with an optional reason.send_payment_request_cancellation(link, app_id, event: &PaymentRequestCancellation) -> Result<()>Sends a unilateral cancellation with an optional reason.send_payment_proof(link, app_id, event: &PaymentProof) -> Result<()>Sends method-specific proof data for one concrete payment execution. The requested amount is inherited from immutable Payment Request terms and is not repeated in the generic Payment Proof. The opaqueproofobject is method-specific and has no required generic discriminator. Thepayment_referencemust be copied from the accepted Payment Request; recurring proofs include aBillingPeriod.PaymentProof::validate_for_request(&request) -> Result<()>Validates stateless proof/request correlation fields: matching Payment Request ID and Payment Reference, one-time vs recurring Billing Period presence, Billing Period shape when present, and accepted Payment Endpoint Identifier. Caller-managed application or wallet state must still decide whether the request is known, accepted, proposal-expired before acceptance, rejected, cancelled, already processed or settled, whether the sender role is allowed for the message kind, or whether a recurring Billing Period is eligible under the request recurrence.PaymentProof::validate_conversion_quote(&request, quote) -> Result<()>Also validates a selected quote’s request, Billing Period and accepted payment asset. Wallets still verify the actual payment amount and time against the accepted terms and quote.
Payment Request, Allowance, and Receipt Access messages use Event Message semantics. Use EncryptedLink::receive_private_application_messages, persist the returned raw stream messages, then parse/reroute them with stateless parsers such as parse_payment_request_event_message, parse_allowance_event_message, parse_receipt_access_event_message, and parse_private_payment_list_json.
Paykit Library is stateless and does not persist Event Message history. Callers that derive state or trigger side effects must persist the raw JSON payload, parsed kind when available, parse result, and parsed IDs when available from event wrappers such as PaymentRequestEventMessage or ReceiptAccessEventMessage, detect conflicting reused Event IDs or conflicting repeated payment_request_id terms, and apply lifecycle rules such as proof-after-rejection/cancellation before acting.
Callers that persist Encrypted Link snapshots should treat the snapshot as the local read checkpoint. Persist received Event Messages and dedupe state before replacing the stored snapshot with a snapshot whose read counter has advanced past those messages. If events are persisted but the snapshot is not, replay is expected; Event Messages should be deduped by event_id, while Receipt Access can also be reconciled by Receipt ID and caller receipt state.
§Allowance exchange
An Allowance is private, scoped authority from an Allower for automatic handling of compatible Payment Requests sent by an Allowee. The four V1 kinds are proposal, acceptance, rejection, and End Event Messages. AllowanceTermsBuilder constructs immutable terms, while AllowanceAcceptance::validate_for_proposal, AllowanceRejection::validate_for_proposal, and the two AllowanceEnd validation helpers check authenticated party roles and causal references without storing lifecycle state.
serialize_allowance_event(event: &AllowanceEvent) -> Result<String>serializes closed V1 JSON and enforces the 1000-byte whole-message limit.parse_allowance_event_message(message: &PrivateApplicationMessage) -> Option<AllowanceEventMessage>parses recognized events while preserving raw JSON and returning redacted structural failures.send_allowance_proposal,send_allowance_acceptance,send_allowance_rejection, andsend_allowance_endsend typed events over an established Encrypted Link.
match_allowance_request evaluates exact asset, inclusive amount range, and the
allowed Payment Endpoint Identifier intersection. check_allowance_time checks
the active window and watermark without evaluating capacity, for example before
recurring Acceptance. evaluate_allowance additionally
checks the active window, a caller-supplied trusted time and durable watermark,
and every period/lifetime limit against complete committed automatic usage and
unresolved reservations. allowance_period_window exposes UTC anchored or rolling
boundaries, and compare_decimal_amounts / add_decimal_amounts provide exact
decimal arithmetic without an asset precision limit. Inputs retain their original
wire spelling; arithmetic results are numerically normalized.
These functions are pure checks, not payment authorization. AllowanceUsageEntry
represents one already-admitted automatic occurrence; each evaluation adds one
candidate count and its complete requested amount. The SDK must establish that
the history and watermark are current and complete, exclude released reservations
and manual payments from usage, check lifecycle and exact party scope, deduplicate
all payment paths, and atomically reserve capacity before execution. An empty
usage slice is not evidence of an unused Allowance. Restoring an old snapshot does
not establish accounting freshness. A successful evaluation changes no state.
Paykit Library does not derive Allowance lifecycle state, persist usage, reserve capacity, select an Allowance or Payment Endpoint, or execute payment. The caller/SDK must durably preserve both directions of authenticated history and enforce cross-kind Event ID dedupe. Session creation, capability scope, key rotation, Pubky client timeouts, and wallet payment policy remain caller duties.
§Payment receipts
Receipts involve three related objects:
- The plaintext
Receiptis created and decrypted locally. It is not stored directly on the homeserver. - The Encrypted Receipt is stored on the issuer’s homeserver under
/pub/paykit/v0/private/receipts/{ReceiptId}. - A
ReceiptAccessdescriptor is sent to the counterparty over the existing Encrypted Link. It contains the Event ID,ReceiptId,payment_reference, optionalpayment_request_idandbilling_period, Receipt Location, and symmetric Receipt Decryption Key.
Receipt Location is a path on the issuer’s homeserver, not a complete Pubky resource by itself. SDK/runtime code pairs it with the Receipt Access sender/issuer context when retrieving the Encrypted Receipt. The Receipt is encrypted with XChaCha20Poly1305; the storage location path is used as authenticated associated data, so fetching the right ciphertext but decrypting it against a different location fails.
prepare_receipt(link, draft: ReceiptDraft) -> Result<PreparedReceipt>Builds a canonical localReceiptfrom the caller’sReceiptDraft, fills in the recipient public key fromlink, generates a freshReceiptIdwhen the draft does not provide one, copies optional Payment Request ID and Billing Period correlation into the Receipt and Receipt Access descriptor, generates a freshReceiptDecryptionKey, encrypts the Receipt into an Encrypted Receipt, and returns the matchingReceiptAccessdescriptor without storing or sending anything. Receipt Metadata is a caller-defined JSON object.prepare_receipt_for_recipient(recipient_public_key, draft: ReceiptDraft) -> Result<PreparedReceipt>Same asprepare_receipt, but takes the recipient public key directly so stateful runtimes can prepare receipt issuance before restoring or sending over an Encrypted Link.store_prepared_receipt(session, prepared: &PreparedReceipt) -> Result<()>Stores the Encrypted Receipt from a prepared issuance at its Receipt Location.send_receipt_access(link, app_id, access: &ReceiptAccess) -> Result<()>Sends a prepared Receipt Access descriptor over Noise. This can be retried with the same descriptor if storage already succeeded.serialize_receipt_access_json(app_id, access: &ReceiptAccess) -> Result<String>Returns the canonical Receipt Access Event Message JSON for durable outbound queues.parse_receipt_access_event_message(message: &PrivateApplicationMessage) -> Option<ReceiptAccessEventMessage>Stateless parser for Receipt Access events from the raw Private Application Message stream. Recognized but malformed Receipt Access events are returned with a validation error so callers can persist the raw payload before advancing their durable checkpoint.parse_receipt_access_json(json: &str) -> Result<ReceiptAccess>Stateless parser for a known Receipt Access JSON payload.ReceiptAccess::location_for(receipt_id) -> StringReturns Paykit’s canonical Receipt Location for an Encrypted Receipt.Receipt::encrypt(&self, key) -> Result<String>/Receipt::decrypt(encrypted_json, key, location) -> Result<Receipt>Encrypts local plaintext Receipts into Encrypted Receipts, or decrypts Encrypted Receipts back into local plaintext Receipts, usingXChaCha20Poly1305. Encryption derives the canonical Receipt Location path from the Receipt’sReceiptIdand authenticates that path as AAD. Pass the exact location from the access descriptor when decrypting; it is authenticated as AAD. Decryption also rejects plaintext whose internal Receipt ID does not match the authenticated location.decrypt_receipt(encrypted_json, key, location) -> Result<Receipt>Convenience wrapper aroundReceipt::decrypt. This decrypts with the supplied location as authenticated data and rejects plaintext whoseReceiptIddoes not map to that location. Receipt Access descriptor validation happens when parsing or sending Receipt Access.
Receipt Decryption Keys are sensitive. ReceiptDecryptionKey and ReceiptAccess redact key material from formatted output through the key’s custom Debug/Display, but callers must still avoid logging or persisting the raw ReceiptDecryptionKey::as_str() value outside secure storage.
Apps should call prepare_receipt, persist the returned PreparedReceipt or equivalent issuance state, then call store_prepared_receipt and send_receipt_access in retryable steps. If storage succeeds but sending Receipt Access fails, callers can retry sending the same PreparedReceipt::access.
§Termination
close_encrypted_link(link: EncryptedLink) -> Result<()>Closes the Noise session and releases resources.
§Handshake Polling Patterns
The caller controls the polling strategy for advance_handshake. Two common patterns:
Fixed interval:
use std::time::Duration;
use paykit_lib::{advance_handshake, HandshakeAdvanceError, HandshakeProgress, EncryptedLinkHandshake};
async fn poll_fixed(mut handshake: EncryptedLinkHandshake) -> Result<paykit_lib::EncryptedLink, HandshakeAdvanceError> {
loop {
match advance_handshake(handshake).await? {
HandshakeProgress::Pending(h) => {
handshake = h;
tokio::time::sleep(Duration::from_millis(100)).await;
}
HandshakeProgress::Complete(link) => return Ok(link),
}
}
}With timeout:
use std::time::{Duration, Instant};
use paykit_lib::{advance_handshake, HandshakeAdvanceError, HandshakeProgress, EncryptedLinkHandshake};
async fn poll_with_timeout(mut handshake: EncryptedLinkHandshake) -> Result<paykit_lib::EncryptedLink, HandshakeAdvanceError> {
let deadline = Instant::now() + Duration::from_secs(60);
loop {
if Instant::now() > deadline {
return Err(paykit_lib::PaykitError::Transport {
context: "handshake timed out".into(),
source: anyhow::anyhow!("deadline exceeded"),
}
.into());
}
match advance_handshake(handshake).await? {
HandshakeProgress::Pending(h) => {
handshake = h;
tokio::time::sleep(Duration::from_millis(100)).await;
}
HandshakeProgress::Complete(link) => return Ok(link),
}
}
}Both polling examples propagate the complete advance error, including any retry handle, to their caller. The timeout generated by the second example has no retry handle. Session creation, capability scope, and key rotation remain the caller’s responsibility.
§Session Resumption
The handshake checkpointing API above covers in-progress handshakes.
An established EncryptedLink can be snapshotted, serialized to bytes, persisted to durable storage, and later restored without re-doing the Noise handshake. This enables session resumption after app restarts or in-process recovery.
Snapshot and serialize:
EncryptedLink::snapshot() -> Result<EncryptedLinkSnapshot>Captures the current Encrypted Link state (transport keys, nonce counters, and counterparty identity) as a serializable snapshot. Fails while a prepared send is unacknowledged; seeretry_pending_send.EncryptedLink::serialize() -> Result<Vec<u8>>Convenience method equivalent toself.snapshot()?.serialize().EncryptedLink::retry_pending_send() -> Result<()>Republish the prepared packet retained after a send exhausted its retry budget. Until it is republished, sends, receives, and snapshots on this link fail. Restoring an older snapshot is not a safe recovery: the failed write may have reached the homeserver, so rolling back the sending nonce and slot can reuse the transport key and nonce. Only republish the retained packet or establish a fresh link.EncryptedLink::config() -> &Arc<PubkyNoiseConfig>Access the shared Noise configuration for in-process restore viarestore_encrypted_link_from_config.
Snapshot type:
EncryptedLinkSnapshot::serialize() -> Vec<u8>Serializes thepubky-noisesession state followed by the counterparty’s 32-byte Noise public key and 72-byte recovery context. The counterparty Pubky identity key remains embedded in the Noise state.EncryptedLinkSnapshot::deserialize(bytes: &[u8]) -> Result<EncryptedLinkSnapshot>Reconstructs a snapshot from bytes, including the embedded recipient public key.EncryptedLinkSnapshot::recipient() -> &PublicKeyAccess the counterparty’s public key embedded in the snapshot.EncryptedLinkSnapshot::remote_noise_public_key() -> &PublicKeyAccess the counterparty’s identity-wide Noise public key embedded in the snapshot.
Restore:
restore_encrypted_link(session, secret_key, remote_identity_public_key, outbox_client, snapshot) -> Result<EncryptedLink>Cross-restart restore. Accepts a freshPubkySessionand the same secret key used in the originalinitiate_encrypted_linkoraccept_encrypted_linkcall. Internally builds a newPubkyNoiseConfigand restores the transport-phase Noise state and counters directly from the serialized snapshot.restore_encrypted_link_from_config(config, remote_identity_public_key, snapshot) -> Result<EncryptedLink>In-process restore. Reuses an existingArc<PubkyNoiseConfig>(obtainable viaEncryptedLink::config()) when the link needs rebuilding without an app restart.
Both handshake and established-link restore validate that supplied config paths match the Pubky identity pair and Noise keys before restoring Noise state.
After link restore, max_send_retries resets to DEFAULT_MAX_SEND_RETRIES. Call EncryptedLink::set_max_send_retries after restore if you need a non-default value.
Recovery markers:
EncryptedLinkRecoveryMarker is a minimal public Pubky marker for relink
coordination when an Encrypted Link can no longer be trusted. paykit-lib
provides stateless marker parsing, serialization, path derivation, and
publish/fetch/remove helpers. SDKs decide when to publish or act on markers.
Marker derivation uses the same sorted Pubky identity pair under the distinct
paykit-link-recovery-v0 domain, retaining the Noise DH secret. Pure path and
unauthenticated fetch helpers require both identities explicitly; publish,
remove, and outbox cleanup helpers take the remote identity and obtain the
local identity from the supplied session.
When to snapshot:
Take a snapshot after the Encrypted Link is established and periodically after exchanging messages. The snapshot includes nonce counters that must stay in sync with the counterparty. Restoring a snapshot taken before a later send rolls back the sending nonce and outbox slot, so the next send reuses the transport key and nonce; establish a fresh Encrypted Link instead. Never send different plaintext from a snapshot taken before a failed send: if the earlier publish reached the homeserver, that reuses the transport key and nonce. Persist any returned Event Messages and caller dedupe state before replacing the stored snapshot with one whose read counter has advanced past those messages.
Snapshot bytes include sensitive key material, so they must be treated as secrets (store encrypted at rest; never log or expose them).
// After establishing the link:
let link: EncryptedLink = /* ... handshake complete ... */;
let bytes = link.serialize()?;
save_to_disk(&bytes);
// After app restart:
let bytes = load_from_disk();
let snapshot = EncryptedLinkSnapshot::deserialize(&bytes)?;
let remote_pubkey = snapshot.recipient().clone();
let mut link = restore_encrypted_link(
fresh_session, secret_key, &remote_pubkey, outbox_client, snapshot,
).await?;
// Continue using set_private_payment_list and raw stream receive/parsing§Exports
Key exports include:
PaykitAppId,PaykitApp,PaykitAppRegistry, and its read/publish helpers for identity-wide app discovery and payment preferences.with_write_lockfor Pubky read-modify-write operations. Encrypted shared SDK state and rotatable Paykit key material are provided bypaykit-sdk, not this stateless crate.PAYKIT_PATH_PREFIX(/pub/paykit/v0/) andPAYKIT_PRIVATE_PATH_PREFIX(/pub/paykit/v0/private) to standardize Pubky path construction.set_payment_endpoint,remove_payment_endpoint,get_payment_list, andget_payment_endpointfor Public Payment Endpoint operations overpubky::PubkySessionandpubky::PublicStorage.EncryptedLink,EncryptedLinkHandshake,HandshakeProgress,EncryptedLinkSnapshot,EncryptedLinkHandshakeSnapshot,PrivateApplicationMessage, andPrivateMessageKindfor Encrypted Link types.initiate_encrypted_link,accept_encrypted_link,advance_handshake,close_encrypted_link,EncryptedLink::receive_private_application_messages,set_private_payment_list, andparse_private_payment_list_jsonfor Encrypted Link and Private Payment List operations.PaymentAmount,PaymentRequest,PaymentRequestEvent,PaymentRequestEventMessage,PaymentRequestAcceptance,PaymentRequestRejection,PaymentRequestCancellation,PaymentProof,send_payment_request,serialize_payment_request_event,parse_payment_request_event_message, and proof validation helpers for Payment Request exchange.AllowanceId,AllowanceTerms,AllowanceEvent,AllowanceEventMessage, the four typed Allowance lifecycle events,serialize_allowance_event,parse_allowance_event_message, and typed send helpers for stateless Allowance exchange.ReceiptId,ReceiptDraft,Receipt,PreparedReceipt,ReceiptAccess,ReceiptAccessEventMessage,ReceiptDecryptionKey,prepare_receipt,store_prepared_receipt,send_receipt_access,parse_receipt_access_event_message,parse_receipt_access_json,decrypt_receipt, andENCRYPTED_RECEIPT_MAX_BYTESfor Encrypted Receipt issuance, access delivery, decryption, and encrypted-document sizing.restore_encrypted_link,restore_encrypted_link_from_config,restore_encrypted_link_handshake,restore_encrypted_link_handshake_from_configfor session resumption after app restart or in-process recovery.DEFAULT_MAX_RECOVERY_ATTEMPTS,DEFAULT_MAX_SEND_RETRIESfor configurable retry/recovery limits.pubky_noisere-export for advanced callers that need direct access to the encryption layer.
Re-exports§
pub use pubky_noise;
Structs§
- Allowance
Acceptance - Acceptance Event Message correlated to one Allowance Proposal.
- Allowance
Amount Range - Inclusive per-payment amount range, preserving decimal wire spellings.
- Allowance
End - Terminal End Event Message for a proposed or accepted Allowance.
- Allowance
Evaluation - Successful common-rule evaluation; this does not authorize or reserve payment.
- Allowance
Evaluation Input - Explicit inputs to common eligibility math, without lifecycle or payment authority.
- Allowance
Event Message - A recognized Allowance Event Message plus its redacted parse result.
- Allowance
Id - UUID-v4 identifier shared by one Allowance lifecycle.
- Allowance
Period - Validated anchored or rolling period used by an Allowance limit.
- Allowance
Period Limit - Amount and/or payment-count ceiling applied over one period.
- Allowance
Period Window - One exact UTC usage window: anchored
[start, end)or rolling(start, end]. - Allowance
Proposal - Proposal Event Message for exact Allowance Terms.
- Allowance
Rejection - Rejection Event Message correlated to one Allowance Proposal.
- Allowance
Terms - Immutable constraints proposed for one Allowance.
- Allowance
Terms Builder - Builder for immutable
AllowanceTerms. - Allowance
Usage Entry - One committed automatic payment or unresolved automatic reservation.
- Billing
Period - Time interval a recurring Payment Proof applies to.
- Conversion
Rate - Units of the payment asset owed per one unit of the requested asset. Values are positive decimal strings; implementations must not use floating point.
- Delivery
Confirmation - Confirmation that a counterparty durably received one Event Message.
- Encrypted
Link - Handle to an established Encrypted Link with a counterparty.
- Encrypted
Link Handshake - Handle to an in-progress Noise handshake.
- Encrypted
Link Handshake Snapshot - Serializable snapshot of an in-progress
EncryptedLinkHandshake. - Encrypted
Link Recovery Context - Recovery attempts bound to one Encrypted Link, in the local peer’s order.
- Encrypted
Link Recovery Marker - Minimal public marker identifying a peer’s current Encrypted Link attempt.
- Encrypted
Link Snapshot - Serializable snapshot of an established
EncryptedLink. - EventId
- UUID-v4 identifier for one Event Message.
- Handshake
Advance Error - A failed handshake advance, optionally retaining unchanged read-retry state.
- Paykit
App - Public description of one application using a Paykit identity.
- Paykit
AppCapabilities - Capabilities advertised by one application in a Paykit identity.
- Paykit
AppId - Stable identifier for one application participating in a Paykit identity.
- Paykit
AppRegistry - Public registry shared by every application using one Paykit identity.
- Paykit
Noise KeyAuthorization - Pubky identity approval of Noise routing and handshake keys at one generation.
- Payment
Amount - Amount of value in a payment flow, expressed as decimal text plus asset.
- Payment
Conversion Quote - Payee-issued rates for one recurring Billing Period. The Event ID is the quote identifier. New quotes never replace earlier quotes.
- Payment
Endpoint Identifier - Machine-readable identifier for a Payment Endpoint.
- Payment
Endpoint Payload - Serialized Payment Endpoint Payload served by a Payment Endpoint.
- Payment
List - Collection of Payment Endpoints keyed by Payment Endpoint Identifiers.
- Payment
Proof paykit.payment_proofEvent Message.- Payment
Reference - Payee-visible correlation reference used to connect payments with Paykit artifacts.
- Payment
Request paykit.payment_requestEvent Message.- Payment
Request Acceptance paykit.payment_request_acceptanceEvent Message.- Payment
Request Cancellation paykit.payment_request_cancellationEvent Message.- Payment
Request Event Message - A recognized Payment Request protocol Event Message plus the raw JSON payload received from the Encrypted Link.
- Payment
Request Id - UUID-v4 identifier for one Payment Request.
- Payment
Request Rejection paykit.payment_request_rejectionEvent Message.- Payment
Request Terms - Payment Request terms set by the payee.
- Payment
Request Terms Builder - Unvalidated builder for immutable Payment Request terms.
- Prepared
Encrypted Link Handshake Step - One locally prepared handshake step, including its durable pending output. Persist the snapshot before publication; session authorization, capability scope, and key rotation remain the caller’s responsibility.
- Prepared
Private Application Message Receive - Inbound private message prepared for atomic application-state persistence.
- Prepared
Private Application Message Send - Outbound private message prepared for atomic persistence before publication.
- Prepared
Receipt - Prepared receipt artifacts ready to store and share.
- Private
Application Message - One Private Application Message received from an Encrypted Link.
- Private
Payment List - Versioned Private Payment List sent over an established Encrypted Link.
- Public
Key - Wrapper around
pkarr::PublicKeythat renders with thepubkyprefix. - Receipt
- Canonical receipt plaintext encrypted before storage.
- Receipt
Access - Receipt Access descriptor sent over the existing Noise channel.
- Receipt
Access Event Message - A recognized Receipt Access Event Message plus the raw JSON payload received from the Encrypted Link.
- Receipt
Decryption Key - Symmetric key used to decrypt an Encrypted Receipt.
- Receipt
Draft - Caller-provided receipt fields.
prepare_receiptfills in the recipient public key from the established Encrypted Link before encrypting storage. - Receipt
Id - UUID-v4 identifier for one stored Receipt artifact.
- Recurrence
- Schedule object for a recurring Payment Request.
- Recurrence
Config - Unvalidated input for a recurring Payment Request schedule.
Enums§
- Allowance
Evaluation Block - Why the common Allowance rules did not admit a candidate payment.
- Allowance
Event - Any V1 Allowance lifecycle Event Message.
- Allowance
Period Kind - Usage-period shape used by an Allowance limit.
- Allowance
Period Unit - Unit used by an Allowance period.
- Allowance
Role - A party’s role in one Allowance.
- Handshake
Progress - Result of a single
advance_handshakestep. - Paykit
Error - Domain-specific error type.
- Payment
Conversion - Conversion policy agreed in immutable Payment Request terms.
- Payment
Deadline - Payment deadline, independent of the deadline for accepting a proposal.
- Payment
Request Event - One recognized Payment Request protocol Event Message in FIFO receive order.
- Private
Message Kind - Private Message Kind values understood by Paykit.
- Recurrence
Unit - Recurrence unit for recurring Payment Requests.
Constants§
- DEFAULT_
MAX_ RECOVERY_ ATTEMPTS - Default maximum number of consecutive automatic recovery attempts before
advance_handshakegives up and returns an error. - DEFAULT_
MAX_ SEND_ RETRIES - Default maximum number of automatic Private Application Message
send_messageretries before Paykit gives up and returns an error. - ENCRYPTED_
RECEIPT_ MAX_ BYTES - Maximum encoded size of one stored Encrypted Receipt.
- INITIAL_
PAYKIT_ KEY_ GENERATION - Initial generation for identity-wide Paykit key material.
- PAYKIT_
APP_ REGISTRY_ MAX_ APPS - Maximum number of applications in one Paykit App Registry.
- PAYKIT_
APP_ REGISTRY_ MAX_ BYTES - Maximum serialized Paykit App Registry size accepted from public storage.
- PAYKIT_
APP_ REGISTRY_ MAX_ ENDPOINT_ DEFAULTS - Maximum number of endpoint-specific application defaults in one registry.
- PAYKIT_
APP_ REGISTRY_ PATH - Public path for the identity-wide Paykit App Registry.
- PAYKIT_
ENCRYPTED_ LINK_ RECOVERY_ PATH_ PREFIX - Conventional prefix for Encrypted Link recovery markers.
- PAYKIT_
NOISE_ KEY_ AUTHORIZATION_ PATH - Identity-authorized current Noise key, outside delegated Paykit write access.
- PAYKIT_
PATH_ PREFIX - Conventional prefix for public Paykit data hosted on Pubky storage.
- PAYKIT_
PRIVATE_ PATH_ PREFIX - Conventional prefix for private (encrypted) Paykit data.
- PAYKIT_
SHARED_ STATE_ PATH - Pubky path for the encrypted identity-wide SDK state.
- PAYKIT_
SHARED_ STATE_ WRITE_ PATH_ PREFIX - Prefix for empty markers identifying unconfirmed shared-state writes.
- PAYMENT_
ENDPOINT_ PAYLOAD_ MAX_ BYTES - Maximum encoded size of one public Payment Endpoint payload.
- PAYMENT_
LIST_ MAX_ ENDPOINTS - Maximum number of public Payment Endpoints fetched for one Paykit App.
- PAYMENT_
REFERENCE_ MAX_ LEN - Maximum Payment Reference length in Unicode scalar values.
- PRIVATE_
APPLICATION_ MESSAGE_ RECEIVE_ LIMIT - Maximum encrypted stream slots consumed by one receive call.
Functions§
- accept_
encrypted_ link - Accepts a Noise XX Encrypted Link Handshake from a counterparty (responder role).
- add_
decimal_ amounts - Add valid Payment Amount decimal spellings exactly, without a precision limit.
- advance_
handshake - Advances the handshake by one step.
- allowance_
period_ window - Calculate a usage period at an explicit trusted time without reading a clock.
- check_
allowance_ time - Check the active window and durable trusted-time watermark without consuming capacity.
- clear_
encrypted_ link_ outbox - Delete all encrypted stream slots written by the local identity for one counterparty and recovery context.
- close_
encrypted_ link - Closes an Encrypted Link and cleans up the Noise session state.
- compare_
decimal_ amounts - Compare valid Payment Amount decimal spellings numerically, without rounding.
- content_
revision - Content fingerprint used to detect an application-level stale edit.
- create_
paykit_ app_ registry - Create the identity-wide Paykit App Registry if it does not exist.
- create_
payment_ endpoint - Creates a public Payment Endpoint only when it is currently absent.
- decrypt_
receipt - Decrypts an Encrypted Receipt fetched from a homeserver.
- delete_
resource_ if_ revision - Remove a resource only if its content revision still matches under a lock.
- derive_
paykit_ noise_ public_ key - Derive the identity-wide Paykit Noise public key from a Paykit identity secret.
- derive_
paykit_ noise_ secret_ key - Derive the identity-wide Paykit Noise secret key from a Paykit identity secret.
- encrypted_
link_ recovery_ marker_ paths - Compute local write and remote read paths for recovery markers.
- evaluate_
allowance - Check static matching, active time, watermark, and every amount/count limit.
- fetch_
encrypted_ link_ recovery_ marker - Fetch a counterparty’s recovery marker, if one is present.
- fetch_
payment_ endpoint_ revision - Reads an owned Payment Endpoint’s fingerprint for conditional repair or removal.
- fetch_
resource_ revision - Reads a resource’s content fingerprint without decoding its bytes.
- get_
paykit_ app_ registry - Fetch the identity-wide Paykit App Registry, if it exists.
- get_
paykit_ app_ registry_ with_ revision - Fetch the identity-wide Paykit App Registry and its content revision.
- get_
paykit_ noise_ key_ authorization - Read and verify the identity’s current Noise key. Missing records return
None. - get_
payment_ endpoint - Retrieves a specific Payment Endpoint for
payeeandidentifier. - get_
payment_ endpoint_ with_ revision - Retrieves a specific public Payment Endpoint and its strong revision.
- get_
payment_ list - Retrieves the public Payment List for the given payee.
- get_
payment_ list_ with_ budget - Fetch an app’s public Payment Endpoints using a budget shared across app loads.
- get_
payment_ list_ with_ limits - Fetch an app’s public Payment Endpoints within caller-supplied aggregate limits.
- initiate_
encrypted_ link - Initiates a Noise XX Encrypted Link Handshake with a counterparty (initiator role).
- is_
payment_ list_ limit_ exceeded - Return whether a Payment List fetch failed because it exceeded caller-supplied limits.
- is_
write_ conflict - Whether an operation must reread its resource before retrying a write.
- list_
payment_ endpoint_ identifiers - Lists one App’s Payment Endpoint Identifiers without loading their payloads.
- match_
allowance_ request - Match immutable request terms against an Allowance without lifecycle or time checks.
- parse_
allowance_ event_ message - Parse a raw Private Application Message as an Allowance Event Message.
- parse_
delivery_ confirmation_ json - Parse a version-1 Delivery Confirmation, rejecting malformed wire data.
- parse_
encrypted_ link_ recovery_ marker_ json - Parse an Encrypted Link Recovery Marker JSON payload.
- parse_
paykit_ app_ registry_ json - Parse and validate an identity-wide Paykit App Registry.
- parse_
payment_ request_ event_ message - Parse a raw Private Application Message as a Payment Request protocol event.
- parse_
private_ payment_ list_ json - Parse a versioned Private Payment List JSON message.
- parse_
receipt_ access_ event_ message - Parse a raw Private Application Message as a Receipt Access Event Message.
- parse_
receipt_ access_ json - Parse a Receipt Access JSON message.
- prepare_
receipt - Prepare a plaintext Receipt, Encrypted Receipt, and Receipt Access descriptor without touching the network.
- prepare_
receipt_ for_ recipient - Prepare a plaintext Receipt, Encrypted Receipt, and Receipt Access descriptor for an explicit recipient public key.
- publish_
encrypted_ link_ recovery_ marker - Publish a local recovery marker and return the path written.
- publish_
paykit_ noise_ key_ authorization - Publish a signed Noise key authorization under an exclusive homeserver lock.
- put_
resource_ if_ revision - Replace a resource after checking its content revision under a write lock.
- remove_
encrypted_ link_ recovery_ marker - Remove the local recovery marker for a counterparty.
- remove_
payment_ endpoint - Removes a public payment endpoint from the authenticated Pubky session.
- remove_
payment_ endpoint_ if_ revision - Removes a public Payment Endpoint only at the supplied strong revision.
- restore_
encrypted_ link - Restores an
EncryptedLinkfrom a previously saved snapshot. - restore_
encrypted_ link_ from_ config - Restores an
EncryptedLinkfrom a previously saved snapshot using an existing Noise configuration. - restore_
encrypted_ link_ handshake - Restores an
EncryptedLinkHandshakefrom a previously saved snapshot. - restore_
encrypted_ link_ handshake_ from_ config - Restores an
EncryptedLinkHandshakefrom a previously saved snapshot using an existing Noise configuration. - send_
allowance_ acceptance - Send a
paykit.allowance_acceptanceEvent Message. - send_
allowance_ end - Send a
paykit.allowance_endEvent Message. - send_
allowance_ proposal - Send a
paykit.allowance_proposalEvent Message. - send_
allowance_ rejection - Send a
paykit.allowance_rejectionEvent Message. - send_
payment_ conversion_ quote - Send payee-issued rates for one recurring Billing Period. The caller owns role, session capabilities, key rotation and recurrence eligibility.
- send_
payment_ proof - Send a
paykit.payment_proofEvent Message. - send_
payment_ request - Send a
paykit.payment_requestEvent Message. - send_
payment_ request_ acceptance - Send a
paykit.payment_request_acceptanceEvent Message. - send_
payment_ request_ cancellation - Send a
paykit.payment_request_cancellationEvent Message. - send_
payment_ request_ rejection - Send a
paykit.payment_request_rejectionEvent Message. - send_
receipt_ access - Send a prepared Receipt Access descriptor over an Encrypted Link.
- serialize_
allowance_ event - Serialize a V1 Allowance Event Message to compact JSON.
- serialize_
delivery_ confirmation - Serialize a Delivery Confirmation into its compact JSON wire representation.
- serialize_
encrypted_ link_ recovery_ marker - Serialize an Encrypted Link Recovery Marker to canonical JSON.
- serialize_
paykit_ app_ registry - Serialize an identity-wide Paykit App Registry.
- serialize_
payment_ request_ event - Serialize a Payment Request protocol Event Message to canonical JSON.
- serialize_
private_ payment_ list_ json - Serialize a Private Payment List into its JSON wire representation.
- serialize_
receipt_ access_ json - Serialize an app-attributed Receipt Access Event Message.
- set_
payment_ endpoint - Stores or updates a public payment endpoint in the authenticated Pubky session.
- set_
private_ payment_ list - Encrypts and sends a complete Private Payment List via the established Encrypted Link.
- store_
prepared_ receipt - Store a prepared Encrypted Receipt at its Receipt Location.
- update_
paykit_ app_ registry - Replace the identity-wide Paykit App Registry if its content still matches.
- update_
payment_ endpoint - Replaces a public Payment Endpoint only at the supplied strong revision.
- with_
write_ lock - Run a Pubky read-modify-write operation under an exclusive file lock.
Type Aliases§
- Result
- Common result alias for Paykit operations.