Documentation
SDKs and libraries
Official TypeScript, Go, and Python clients.
Official clients wrap the REST API with typed resources, automatic retries, and cursor pagination you do not have to write yourself. Community libraries are welcome; the ones below are maintained by us and versioned alongside the API.
TypeScript / Node#
npm install @juicepay/nodeimport { JuicePay } from "@juicepay/node";
const juicepay = new JuicePay(process.env.JUICEPAY_KEY!, {
maxRetries: 4,
timeout: 12_000,
environment: "sandbox",
});
const intent = await juicepay.paymentIntents.create(
{
amount: "125.00",
asset: "USDC",
reference: "INV-1042",
accepted_chains: ["base", "solana"],
},
{ idempotencyKey: "order:ord_8812:intent" },
);The client retries 429, 500, and 502 with exponential backoff and jitter, and honours Retry-After. It never retries a 400 — that is your bug, and retrying it just makes noise.
React components#
npm install @juicepay/reactimport { JuicePayCheckout } from "@juicepay/react";
<JuicePayCheckout
clientSecret={clientSecret}
onComplete={() => router.replace("/orders/complete")}
appearance={{ theme: "juice", primaryColor: "#f9a307" }}
/>The embedded checkout is the same surface as the hosted page, so a customer sees identical copy and identical fee disclosure in both.
Python#
pip install juicepayfrom juicepay import JuicePay
client = JuicePay(api_key=os.environ["JUICEPAY_KEY"])
intent = client.payment_intents.create(
amount="125.00",
asset="USDC",
reference="INV-1042",
accepted_chains=["base", "solana"],
idempotency_key="order:ord_8812:intent",
)Auto-pagination is exposed as an iterator:
for payout in client.payouts.list(status="settled"):
record(payout)Go#
go get github.com/juicepay/juicepay-goclient := juicepay.New(os.Getenv("JUICEPAY_KEY"))
intent, err := client.PaymentIntents.Create(ctx, &juicepay.PaymentIntentParams{
Amount: juicepay.String("125.00"),
Asset: juicepay.String("USDC"),
Reference: juicepay.String("INV-1042"),
AcceptedChains: []string{"base", "solana"},
}, juicepay.WithIdempotencyKey("order:ord_8812:intent"))Webhook helpers#
Each SDK exposes the same verification surface. Use the helper rather than reimplementing HMAC comparison — constant-time comparison matters and is easy to get wrong.
const event = juicepay.webhooks.constructEvent(rawBody, signature, secret);event = client.webhooks.construct_event(raw_body, signature, secret)CLI#
brew install juicepay/tap/juicepay| Command | Purpose |
|---|---|
juicepay listen | Tunnel webhooks to localhost and print a signing secret. |
juicepay trigger | Emit any event type against a sandbox object. |
juicepay logs | Tail API requests for a key. |
juicepay replay | Replay a delivery window to an endpoint. |
juicepay verify | Validate a batch CSV before submission. |
Versioning#
The API is versioned by date in the path: /v1/. Breaking changes ship behind a new version, and the previous one is supported for at least twelve months with a documented migration path. Additive changes — new fields, new event types, new optional parameters — ship without a version bump, so parse defensively and ignore fields you do not recognise.
Staying current#
juicepay logs --followSubscribe to the changelog for a reverse-chronological feed of every change, including the ones that will not affect you.