@zappyquote/sdk
v0.1.1
Published
Official Zappy API client for JavaScript/TypeScript - a thin wrapper over the documented Zappy API v1.
Maintainers
Readme
@zappyquote/sdk
The official JavaScript/TypeScript client for the Zappy API v1 - a thin wrapper over the documented HTTP API (https://zappyquote.com/developers/). The server stays authoritative for pricing, caps, idempotency and ownership; this package only carries requests and maps the public error envelope into typed errors.
Version 0.1.1 · contract openapi-1.0.0@9dff9fdfbcd8c1bd · Node 18+ · zero dependencies · types included · MIT
# official download (always available):
curl -O https://zappyquote.com/dl/zappy.mjs # types: https://zappyquote.com/dl/zappy.d.ts
# npm, ONLY once https://zappyquote.com/developers/ lists @zappyquote/sdk as published by Zappy:
# npm install @zappyquote/sdkimport { Zappy, ZappyError, newIdempotencyKey } from './zappy.mjs'; // or from '@zappyquote/sdk' when installed from npm
const zappy = new Zappy(); // reads ZAPPY_API_KEY; or new Zappy({ apiKey })
const { capabilities } = await zappy.capabilities(); // free
const quote = await zappy.quote({ capability: 'zappy-image-pro' }); // free, reserves nothing
// BILLABLE. maxCredits is a hard ceiling; the idempotency key makes a replay return the same job, never a second charge.
const key = newIdempotencyKey('order-123');
const r = await zappy.createImage({ prompt: 'a lighthouse at dusk', maxCredits: quote.credits_quoted, idempotencyKey: key });
const job = r.status === 'succeeded' ? r : await zappy.waitForJob(r.job_id); // 202 => poll (free)
const asset = await zappy.getAsset(job.assets[0].asset_id); // short-lived signed URL on Zappy's hostErrors
Every failure is a ZappyError subclass with code (the public error code), status, requestId, rateLimit
({limit, remaining, reset}) and retryAfter: ZappyAuthError (401 / insufficient_scope / not configured),
ZappyRateLimitError (429), ZappySpendError (ceiling, cap, balance, idempotency), ZappyNotFoundError,
ZappyUnavailableError (502/503, not available), ZappyTransportError (network, timeout, unreadable). Messages never
contain a credential. Successful results carry _meta with the same metadata.
Webhooks
import { verifyWebhookSignature } from './zappy.mjs'; // or '@zappyquote/sdk'
// rawBody must be the exact bytes received; header is the Zappy-Signature value
if (!verifyWebhookSignature(process.env.ZAPPY_WEBHOOK_SECRET, req.headers['zappy-signature'], rawBody)) return res.status(400).end();OAuth (PKCE)
pkcePair() and authorizeUrl({...}) build the authorization request for an OAuth app you registered in Zappy
(Account -> Developer). Token exchange and consent happen on Zappy's authorization server; this package adds no
second auth implementation. Pass resource: 'https://zappyquote.com/mcp' for a Remote MCP connection.
Paid calls are never retried
createImage / editImage send one request. A retry is your decision - make it with the same idempotencyKey.
