Skip to main content

Professional API: Syncing Your Practice Data

Copy your practice data into your own systems once, then fetch only what has changed since.

What you can sync

Every list on the Orchard72 Professional API supports the same sync pattern: appointments, enquiries, clients, matters, will reviews, engagement letters, invoices, time entries, rate cards, commission statements, referrals, tasks, complaints, reviews, documents, messages and your team.

You need a professional API key with the pro:read scope, sent as Authorization: Bearer <your key>. The getting started guide shows how to create one.

Walking a whole collection

Add ?cursor= (with an empty value) to any list request to switch to cursor pagination. Rows come back oldest change first, and each response carries a next link to the following page. Keep following next until it is null.

  • page_size sets how many rows each page holds, up to 500. Larger values are capped rather than refused.
  • The cursor is opaque. Store and send it back exactly as you received it.
  • The same links are also sent in a standard Link response header with rel="next" and rel="prev".
  • Without cursor, lists use numbered pages (?page=2) and include a total count. Cursor pages leave the count out.

Fetching only what changed

After the first full walk, ask for changes only with updated_since, an ISO-8601 date or date-time. A worked example:

  1. Walk GET /api/v1/pro/ext/appointments/?cursor=&page_size=500 to the end and save every row.
  2. Note the newest updated_at you received, for example 2026-01-31T09:00:00Z.
  3. Next time, request GET /api/v1/pro/ext/appointments/?cursor=&updated_since=2026-01-31T09:00:00Z and walk that to the end.
  4. Upsert each row by its id, then note the new newest updated_at.

The boundary is inclusive, so the row you stopped on last time comes back once more. Upserting by id makes that harmless. A date without a time means midnight UTC, and a time without an offset is read as UTC.

Deletions

Appointments, enquiries, clients, engagement letters, invoices and commission statements record deletions. When a row in one of those is removed, a sync with updated_since tells you so. On the last page only (where next is null) you receive deletion rows shaped like {"id": 42, "deleted": true, "deleted_at": "2026-02-01T10:15:00Z"}. Remove those ids from your copy.

  • A deletion row can name an id you never held. Ignore it.
  • On those collections, deletions are kept for 30 days. If your updated_since is older than that, the API answers 410 Gone with the code sync_window_expired. Walk the whole collection again without updated_since, then resume from the newest updated_at you receive.

Webhooks are a nudge, not the record

A webhook tells you something changed so you can run a sync sooner. Deliveries can be missed, so keep a scheduled updated_since sync as well.

Bulk export by key

For a one-off copy of everything, request an export instead of walking each list.

  1. POST /api/v1/pro/ext/exports/ with no body starts an export and returns the job with 202 Accepted. If one is already being prepared, you get 409 Conflict with that job instead.
  2. Poll GET /api/v1/pro/ext/exports/<id>/ until can_download is true.
  3. Fetch the file from download_url. The link is signed, needs no key, and expires after a few minutes (see download_expires_in), so poll again for a fresh link if it lapses.

Every export request is recorded in your practice’s audit trail.

Rate Limits

Limits are counted on a sliding window. When you go over one, the API answers 429 Too Many Requests with a Retry-After header telling you how long to wait.

Professional API

Every request to /api/v1/pro/ext/.

  • Pro Growth: 2,000 requests per hour
  • Support Service Provider Growth: 2,000 requests per hour
  • Pro Enterprise: unlimited
  • Support Service Provider Enterprise: unlimited
  • Founding Member Pro Growth: 2,000 requests per hour

Shared by every key you hold, so a new key never adds to it. Plans not listed here have no access to this API. Scopes: pro:read, pro:org:read, pro:wills:write.

These figures come from the limits the API enforces, also served as JSON at /api/v1/portfolio/rate-limits/.

Related

  • Organisation keys: sync every seat in your firm with one key.
  • The full reference for each endpoint is in the interactive API documentation at /api/v1/pro/ext/docs/.
  • Changelog: what has changed on the API and how we version it.

Can’t find what you’re looking for?

Our support team is here to help. Contact us and we’ll get back to you as soon as possible.

Contact Support

We use cookies to improve your experience. See our Cookie Policy (opens in a new tab) for details.