wild-apricot-exports
v1.0.1
Published
Export every contact, event, registration, invoice, payment, donation, audit log entry, and uploaded file out of a Wild Apricot account to JSON, CSV, and disk — usable as a CLI (wa-export) or as a Node library.
Downloads
439
Maintainers
Readme
wild-apricot-exports
Export and back up your Wild Apricot data directly, without using the admin UI.
wild-apricot-exports pulls your data out of Wild Apricot via the public REST API (and WebDAV for files) and saves it locally as JSON, CSV, and the original uploaded files. You can use it as a CLI (wa-export) or as a Node library.
API reference: API.md — full programmatic docs (options, return types, defaults, REST helpers, examples).
What gets exported
| Subcommand | Output | Source |
| ------------------------- | ------------------------------------------------------- | ----------------- |
| wa-export config | Account / membership levels / contact fields / settings | REST API |
| wa-export events | All events (with full detail payload) | REST API |
| wa-export registrations | Event registrations | REST API |
| wa-export contacts | Contacts / members | REST API |
| wa-export invoices | Invoices | REST API |
| wa-export payments | Payments | REST API |
| wa-export donations | Donations | REST API |
| wa-export audit-log | Audit log entries | REST API |
| wa-export files | All uploaded files (Documents, Pictures, Logos, etc.) | WebDAV |
| wa-export all | Runs every step above in sequence | REST API + WebDAV |
| wa-export retry-events | Re-fetches events that failed during events | REST API |
REST exports are written as both .json (full payload) and .csv (flattened, spreadsheet-friendly). File exports preserve the original folder structure under exports/files/.
Requirements
- Node.js 20+
- A Wild Apricot account with admin access
- A Wild Apricot API key (Settings → Authorized applications → Authorize application)
- For file export only: your Wild Apricot admin login (email + password) — the WebDAV server does not accept API keys
Install
Global CLI (wa-export on your PATH):
npm install -g wild-apricot-exportsOne-off CLI without a global install (npx can fetch the package when needed). Both binary names point at the same entrypoint:
npx wild-apricot-exports --help
# or
npx wa-export --helpInside another Node project (use the library from code or pin the CLI version alongside your app):
npm install wild-apricot-exportsImport from "wild-apricot-exports" in your code (see Library usage), or run npx wa-export … / npx wild-apricot-exports … from that project’s root so node_modules/.bin is resolved.
Setup
The CLI reads credentials from environment variables (or a .env file in the working directory):
| Variable | Required | Description |
| ----------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------ |
| WILD_APRICOT_API_KEY | REST exporters & all; not files | API key from Settings → Authorized applications (--api-key overrides) |
| WILD_APRICOT_ACCOUNT_ID | no | Auto-discovered if omitted (--account-id overrides) |
| WILD_APRICOT_WEBDAV_URL | only for files | WebDAV base URL (e.g. https://yourorg.wildapricot.org or https://yourdomain/resources) |
| WILD_APRICOT_ADMIN_EMAIL | only for files | Admin login email |
| WILD_APRICOT_ADMIN_PASSWORD | only for files | Admin login password |
| WILD_APRICOT_FILE_DIRS | no | Comma-separated WebDAV directories to crawl (default: full root) |
Quick start with a .env file:
echo "WILD_APRICOT_API_KEY=your-key-here" > .env
wa-export contactsIf you used a local install (npm install wild-apricot-exports without -g), run npx wa-export contacts instead of wa-export contacts.
CLI usage
Run any individual exporter:
wa-export events
wa-export contacts
wa-export invoices --start-date 2026-01-01 --end-date 2026-12-31
wa-export payments
wa-export donations
wa-export registrations
wa-export audit-log
wa-export config
wa-export filesOr run everything at once:
wa-export all
wa-export all --exclude files # skip the slow WebDAV crawl
wa-export all --include events,registrationswa-export all runs each step sequentially and prints a summary at the end. A failure in one step does not stop the others.
Common options:
| Option | Applies to | Description |
| --------------------------------------------------- | ------------------------------------------------- | ---------------------------------------------- |
| --api-key <key> | REST exporters & all | Overrides WILD_APRICOT_API_KEY |
| --account-id <id> | REST exporters & all | Overrides WILD_APRICOT_ACCOUNT_ID |
| -o, --out-dir <dir> | every command | Root output directory (default: ./exports) |
| -q, --quiet | every command | Suppress progress (errors still print) |
| --start-date YYYY-MM-DD / --end-date YYYY-MM-DD | invoices / payments / donations / audit-log / all | Restrict to a date range |
| --include, --exclude | all | Comma-separated step lists |
| --file-dirs | files, all | Comma-separated top-level WebDAV dirs to crawl |
| --request-delay-ms | events, registrations, retry-events | Override the per-request pacing |
| --save-every-n | events, registrations | Checkpoint cadence for resumable runs |
| --inter-file-delay-ms | files, all | Pause between successful WebDAV downloads |
| --max-retries | files, all | Max retry attempts per file |
| --retry-base-ms | files, all | Base delay for exponential backoff on retries |
Throttling and date filters from .env still work when you omit CLI flags (e.g. WA_EVENT_REQUEST_DELAY_MS, WA_EVENTS_SAVE_EVERY, INVOICES_START_DATE / INVOICES_END_DATE, AUDIT_START_DATE, etc.). See .env.example.
wa-export audit-log defaults to the last 30 days when you omit --start-date / --end-date (Wild Apricot only retains a limited audit window anyway).
Run wa-export <subcommand> --help (or npx wa-export <subcommand> --help when the CLI is only installed locally) to see every option for a given command.
Output
Everything is written under ./exports/ (or whatever you pass to --out-dir):
exports/
config/ account.json, membership-levels.json, contact-fields.json, ...
events/ wild-apricot-events.json, wild-apricot-events.csv
_partial.json (resume checkpoint), _detail_failures.json (if any)
registrations/ registrations.json, registrations.csv
registrations.partial.json (resume), _failures.json (if any)
contacts/ contacts.json, contacts.csv
invoices/ invoices.json, invoices.csv
payments/ payments.json, payments.csv
donations/ donations.json, donations.csv
audit-log/ audit-log.json, audit-log.csv
files/ <original folder structure from WebDAV>
_manifest.json (resume + stats)Library usage
The published package is CommonJS (require). TypeScript and many Node ESM setups can still use import via standard interop; plain CommonJS works out of the box.
For the complete reference — every exporter, option default, return type, REST helper, and env var — see API.md.
ESM / TypeScript-style import:
import { exportContacts, exportEvents, exportAll, consoleLogger } from "wild-apricot-exports";
const result = await exportContacts({
apiKey: process.env.WILD_APRICOT_API_KEY!,
outDir: "./exports",
logger: consoleLogger, // omit for silent
});
console.log(`Exported ${result.count} contacts to ${result.csvPath}`);CommonJS require:
const { exportContacts, consoleLogger } = require("wild-apricot-exports");
(async () => {
const result = await exportContacts({
apiKey: process.env.WILD_APRICOT_API_KEY,
outDir: "./exports",
logger: consoleLogger,
});
console.log(`Exported ${result.count} contacts to ${result.csvPath}`);
})();Quick reference
| Category | Exports |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Exporters | exportConfig, exportEvents, retryEventFailures, exportRegistrations, exportContacts, exportInvoices, exportPayments, exportDonations, exportAuditLog, exportFiles, exportAll |
| Loggers | consoleLogger, silentLogger |
| REST helpers | API_BASE, createTokenManager, getAuthAndAccount, discoverAccountId, apiFetch, apiGet, paginate, asyncQuery, sleep |
Baseline options for REST exporters:
interface ExportOptions {
apiKey: string;
accountId?: string | number; // auto-discovered if omitted
outDir?: string; // default: "./exports"
logger?: Logger; // default: silentLogger
onProgress?(event: ProgressEvent): void;
signal?: AbortSignal; // for cancellation
}exportFiles uses WebDAV credentials instead of apiKey. Full option and result docs: API.md. TypeScript definitions: dist/index.d.ts.
Cancellation example:
const ac = new AbortController();
setTimeout(() => ac.abort(), 30_000);
await exportEvents({
apiKey: process.env.WILD_APRICOT_API_KEY!,
signal: ac.signal,
});Notes
- Resumability.
events(_partial.json),registrations(registrations.partial.json), andfiles(_manifest.json) checkpoint progress and resume if interrupted. UseretryEventFailuresaftereventswhen_detail_failures.jsonis present. - Rate limiting. The library handles 429s automatically with exponential backoff (honoring
Retry-Afterwhen present), and refreshes expired access tokens mid-run on 401. - WebDAV uses HTTP Digest auth. Wild Apricot's WebDAV endpoint returns 500 on Basic auth; the file exporter handles this automatically.
- By default,
wa-export filescrawls everything under/recursively (including files at the root). If listing/500s on your account, pass--file-dirsto scope the crawl (e.g.--file-dirs Documents,Pictures,Logos,Theme,SiteUploads). - Audit log retention is limited by Wild Apricot (often 30–90 days depending on plan). Older entries simply return nothing.
- Date filters for invoices, payments, donations, and the audit log are optional. Omit them to fetch everything.
Development
From a git checkout you run the same CLI via node bin/wa-export.js (after npm run build). The npm run export-* script names are convenience aliases that forward to wa-export:
git clone https://github.com/JustinPaoletta/wild-apricot-exports.git
cd wild-apricot-exports
npm install
npm run lint
npm run format:check
npm run build
npm test
npm run test:coverage
node bin/wa-export.js --helpnpm run build:watch rebuilds on save during development.
Contributing
See CONTRIBUTING.md. Code of conduct.
License
MIT License — Copyright (c) 2026 Justin Paoletta. See LICENSE for the full text.
