pay.sh docs
SDKTypeScript

Client

Consume 402-gated APIs from TypeScript with createPayKitClient — a payment-aware fetch that pays and retries automatically.

Unlike the server-only SDKs in other languages, TypeScript also ships the paying side, via @solana/pay-kit/client. createPayKitClient returns a fetch-shaped client: on a 402 it reads the challenge, pays with the matching protocol, and retries the request with the Authorization: Payment credential.

Create a client

import { createPayKitClient } from '@solana/pay-kit/client';
import { createKeyPairSignerFromBytes, getBase58Encoder } from '@solana/kit';
const signer = await createKeyPairSignerFromBytes(getBase58Encoder().encode(SECRET))const client = await createPayKitClient({ signer, rpcUrl: 'http://localhost:8899' })// On a 402, pay-kit pays with the matching protocol and retries — transparently.const res = await client.fetch('https://api.example.com/api/v1/quote/AAPL')console.log(await res.json())

createPayKitClient takes the wallet signer (an @solana/kit KeyPairSigner), an rpcUrl, and an optional accept preference list. The returned client.fetch mirrors the platform fetch.

Force a protocol

When an endpoint advertises both MPP and x402, pass the protocol as the third argument to pin the rail. Omit it to let pay-kit choose.

const signer = await createKeyPairSignerFromBytes(getBase58Encoder().encode(SECRET))const client = await createPayKitClient({ signer, rpcUrl: 'http://localhost:8899' })// Force the x402 rail (omit the 3rd arg to let pay-kit pick MPP or x402).const res = await client.fetch('https://api.example.com/api/v1/quote/AAPL', undefined, 'x402')console.log(await res.json())

Streamed sessions

For a session endpoint, open a payment channel and consume the stream chunk by chunk. The opener signs each off-chain voucher as deliveries arrive; settlement runs on the server when the channel closes.

const client = createSessionFetch({  opener: createPaymentChannelSessionOpener({ signer, rpcUrl }),})const res = await client.fetch('https://api.example.com/api/v1/stream')for await (const chunk of res.body!) {  process.stdout.write(chunk)}

On this page