Server SDKs
Server-side SDKs in TypeScript / Node and Python. Identical surface across both languages — pick the one that matches your stack.
Server SDKs
The Donations SDK ships server-side SDKs in two languages: TypeScript / Node and Python. They expose the same surface — list donations, fetch a donation, refund, list recurring schedules, cancel a schedule, fire a synthetic webhook — and a constant-time HMAC-SHA256 webhook signature verifier that is byte-compatible across every SDK.
Pick the language that matches your existing stack. There is no functional reason to prefer one over another; we maintain both at full parity.
At a glance
| TypeScript / Node | Python | |
|---|---|---|
| Package | @1st-flock/donations-embed-node | onefirstflock-donations-embed |
| Minimum runtime | Node 18.17 | Python 3.10 |
| Style | Async (native fetch) | Async (httpx-based) |
| Models | Plain typed objects | Pydantic v2 |
| Runtime dependencies | None | httpx, pydantic |
| Webhook verifier | Sync, constant-time | Sync + async, constant-time |
The webhook verifier in every SDK is byte-compatible with the platform's outbound signer, so a signature produced by the platform verifies under any SDK; a signature produced for testing by one SDK verifies under any other.
Common surface
Each SDK provides:
- A
Client(or equivalent) constructed with a secret key (sk_live_…/sk_test_…). Publishable keys are rejected at construction with a clear error. listDonations/list_donations/ListDonations— cursor-paginated.getDonation/get_donation/GetDonation— single donation by UUID.refundDonation/refund_donation/RefundDonation— full or partial; idempotent onIdempotency-Key.listRecurring/list_recurring/ListRecurring— cursor-paginated.cancelRecurring/cancel_recurring/CancelRecurring— idempotent.testWebhook/test_webhook/TestWebhook— fires a synthetic event of any type to your configured endpoint.verifyWebhook/verify_webhook/VerifyWebhook— constant-time HMAC-SHA256 verifier, returns a typed event on success and raises a typed exception on failure.idempotencyKey/idempotency_key/IdempotencyKey— generates a tagged UUID suitable for theIdempotency-Keyheader.
Common error model
Every SDK raises a typed exception per HTTP status code so caller code can branch on type rather than parsing status codes manually.
| HTTP | Error class |
|---|---|
| 400 / 422 | ValidationError |
| 401 | AuthError |
| 403 | ForbiddenError |
| 404 | NotFoundError |
| 409 | ConflictError |
| 410 | GoneError |
| 429 | RateLimitError (carries retryAfter / retry_after) |
| 502 | BadGatewayError |
| 503 | ServiceUnavailableError |
| Other | ApiError / APIError |
All errors expose:
- HTTP status code
- A stable machine-readable
codefrom the response body (for examplevalidation_error,card_declined) - A human-readable
message - An optional
detailsobject - A
requestIdcorrelation header value (x-request-id)
Common retry behaviour
Each SDK retries idempotent failures with exponential backoff and jitter. Retries fire on:
- Network errors (connection refused, DNS failure, timeout)
- HTTP 502 / 503 / 504
Retries do not fire on 4xx responses (they are caller errors that re-trying will not fix) or on 429 (you must back off based on the Retry-After header). Mutating endpoints (refundDonation, cancelRecurring) require an Idempotency-Key for safe retry; the SDK's idempotencyKey helper generates a tagged UUID suitable for the Idempotency-Key HTTP header.
Pick your language
- TypeScript / Node — for Node, Bun, Deno (with Node-compat shim), and any other JavaScript-runtime backend.
- Python — for FastAPI, Django, Flask, Starlette, and any other Python web stack. Async-first; integrates naturally with
asyncioandanyio.