Install the PawPlacer SDK from npm for the fastest path to our public API: https://www.npmjs.com/package/pawplacer-sdk.
The package is TypeScript-first. The client and helpers ship with rich typings so editors surface the public API payload shape directly. It wraps the public endpoints, handles retries, memoized caching, validates successful read responses at runtime, checks required create fields before sending writes, honors the hosted API's GET cache headers, and uses idempotency headers for safe create retries by default.
Security reminder: Instantiate the client on the server. The SDK throws if it detects a browser environment unless you explicitly pass
allowBrowser: true(NEVER DO THIS outside local development).
Why use the SDK?
- Typed responses – the
Pet,Person,AdoptionFeeEntry, andContractResponseinterfaces mirror the API responses so you always know which fields are available. - Smart caching – in-memory memoization refreshes results on a schedule you choose while staying within rate limits.
- Retry & error parsing – transient failures are retried automatically and structured API failures surface as normalized SDK errors.
- Server guardrails – the client refuses to instantiate in a browser by default to protect your API keys.
Installation
bun install pawplacer-sdk
# or
npm install pawplacer-sdk
# or
yarn add pawplacer-sdk
No extra @types package is required; the SDK bundles its own declarations.
Track release history in the packaged CHANGELOG.md file, also linked from the npm README.
Integration checklist
- Generate an API key in Settings > SDK & API. Prefer a Read only key for websites and a separate Write + read key only for trusted backend create/sync jobs.
- Store it in server-only environment variables (never client-exposed values).
- Instantiate
PawPlacerClienton the server. - Use
client.pets.list(...),client.people.list(...),client.adoptionFees.get(), orclient.contracts.get(...)for reads. - Use
client.pets.getCustomFields()orclient.people.getCustomFields(type)before sendingcustom_field_dataduring creates.
The SDK & API settings page also includes a copyable quick-start snippet, endpoint scope and rate-limit table, and a Test Your Key health check that runs the SDK methods against your live key.
Quick start
import { PawPlacerClient } from "pawplacer-sdk";
const client = new PawPlacerClient({
apiUrl: process.env.PAWPLACER_API_URL ?? "https://pawplacer.com",
apiKey: process.env.PAWPLACER_API_KEY,
cache: {
enabled: true,
refreshFrequency: 180, // minutes
},
});
// Pets
const pets = await client.pets.list({ status: "available", species: "dog", limit: 12 });
const pet = await client.pets.get("pet-uuid");
// People (adopters & fosters)
const adopters = await client.people.list({ type: "adopter", status: "active" });
const foster = await client.people.create({ type: "foster", name: "Jane Smith", email: "jane@example.com" });
// Adoption fees & contracts
const fees = await client.adoptionFees.get();
const contract = await client.contracts.get("adopter");
cache.refreshFrequency is expressed in minutes. Leave it undefined to keep the 3-hour fallback. Hosted GET responses can still tighten freshness through Cache-Control.
Configuration options
| Option | Description |
|---|---|
apiUrl | Base URL of the PawPlacer API (defaults to production). |
apiKey | Server-side API key for the PawPlacer public API. Required for all SDK calls. |
timeout | Request timeout in milliseconds (default 30000). |
retryLimit / retryBackoffLimit | Control ky's retry strategy for transient failures. |
debug | Enables verbose logging ([PawPlacer SDK] …). |
allowBrowser | Opt-in to browser usage. Leave false to protect credentials. NEVER DO THIS on production. |
cache | Toggle memoization and choose how often cached results refresh. |
Available helpers
Pets
| Method | Summary |
|---|---|
client.pets.list(params?) | Paginated list of public pets with optional filters. |
client.pets.get(id) / client.pets.getById(id) | Fetch a single public pet by ID. |
client.pets.search(query) | Search pets by name, breed, or description. Shorthand for list({ search: query }). |
client.pets.getByStatus(status) | Fetch pets filtered to a specific status label. Shorthand for list({ status }). |
client.pets.getCustomFields() | Retrieve valid field_key values for custom_field_data. |
client.pets.create(payload) | Create a pet (validates required fields before calling the API). |
client.pets.findMany(params?, limit?) | Convenience helper that returns just the data array. |
People (Adopters & Fosters)
All people methods require a type parameter: "adopter" or "foster".
| Method | Summary |
|---|---|
client.people.list(params) | Paginated list of adopters or fosters. |
client.people.get(id, type) / client.people.getById(id, type) | Fetch a single adopter or foster. |
client.people.getCustomFields(type) | Custom field metadata for adopter or foster forms. |
client.people.create(payload) | Create an adopter or foster. Only type and name are required. |
client.people.findMany(params, limit?) | Convenience helper that returns just the data array. |
Adoption Fees & Contracts
| Method | Summary |
|---|---|
client.adoptionFees.get() | Fetch fee rules (species + attribute + adjustment). |
client.contracts.get(type) | Fetch terms & conditions markdown. Types: "adopter", "foster", "volunteer", "surrender". |
Response metadata
After any SDK call, you can inspect the metadata from the last API response:
const meta = client.lastResponseMeta;
// {
// requestId: "3dfabc8f-...",
// apiVersion: "1.3.1",
// generatedAt: "2026-04-14T12:00:00.000Z",
// rateLimit: { limit: 100, remaining: 97, reset: 1713100800 },
// idempotencyReplay: false
// }
| Property | Description |
|---|---|
requestId | Unique request ID for debugging and support. |
apiVersion | Current public API version. |
generatedAt | ISO-8601 timestamp of when the response was generated. |
rateLimit | Object with limit, remaining, and reset (Unix timestamp) for the endpoint's hourly window. |
idempotencyReplay | true if this response was replayed from a previous idempotent create with the same key. |
Endpoint mapping
| SDK method | Endpoint |
|---|---|
client.pets.list(...) | GET /api/pets |
client.pets.getById(...) | GET /api/pets/{petId} |
client.pets.search(...) | GET /api/pets?search=... |
client.pets.getByStatus(...) | GET /api/pets?status=... |
client.pets.getCustomFields() | GET /api/pets/custom-fields |
client.pets.create(...) | POST /api/pets |
client.people.list(...) | GET /api/people?type= |
client.people.getById(...) | GET /api/people/{id}?type= |
client.people.getCustomFields(...) | GET /api/people/custom-fields?type= |
client.people.create(...) | POST /api/people |
client.adoptionFees.get() | GET /api/adoption-fees |
client.contracts.get(...) | GET /api/contracts?type= |
The returned Pet type includes global_adoption_fee when fee rules are configured and the pet has no manual override.
The returned Person type includes tags, custom_field_data, capacity, and status_change_notes.
List endpoints support updated_since (ISO-8601) for incremental sync pulls.
For job-level replay safety, pass your own stable idempotencyKey to client.pets.create(...) or client.people.create(...). The SDK's autogenerated key is scoped to the current invocation.
Prefer another language/runtime? Use the OpenAPI contract at https://pawplacer.com/openapi/public-api-v1.yaml to generate clients outside JavaScript/TypeScript.