Developers

Learn · RxPhoto

Guides & concepts — RxPhoto

The conventions that hold across every RxPhoto resource. Learn these once and the whole API becomes predictable.

ℹ️ RxPhoto is a separate platform

RxPhoto has a different host, auth scheme, field casing, and pagination style from PNE and VISH. If you're on PNE or VISH, see Guides & concepts — PNE & VISH → instead.

Request basics

Pagination

List endpoints are paginated, but the parameters vary by resource — always check the operation's parameter table in the reference. Two styles are in use:

StyleParametersExample resources
Page-basedpage (1-based) and often page_sizepatient, image, gallery (addon exposes only page)
Offset-basedlimit and offsetarea, form

Either way, each list response is an object with a total count, absolute next/previous page URLs (or null at the ends), and the rows in results:

{
  "count": 1287,
  "next": "https://api.rxphoto.com/api/v3/patient/?page=2",
  "previous": null,
  "results": [ { "id": 12345, "first_name": "Jane", ... }, ... ]
}

The simplest way to walk a collection is to follow next until it is null:

def iter_patients(session, base, page_size=50, **filters):
    url = f"{base}/patient/"
    params = {"page_size": page_size, **filters}
    while url:
        res = session.get(url, params=params)
        res.raise_for_status()
        body = res.json()
        yield from body["results"]
        url = body["next"]   # absolute URL to the next page, or None
        params = None        # next already encodes the query string
async function* iterPatients(base, headers, pageSize = 50, filters = {}) {
  const qs = new URLSearchParams({ page_size: pageSize, ...filters });
  let url = `${base}/patient/?${qs}`;
  while (url) {
    const res = await fetch(url, { headers });
    const body = await res.json();
    yield* body.results;
    url = body.next;   // absolute URL to the next page, or null
  }
}
📎 Response envelope

RxPhoto list endpoints wrap rows in a { count, next, previous, results } envelope rather than returning a bare array. Always read from .results, and use .next to advance rather than guessing page counts from count.

Filtering & search

List endpoints expose rich, field-level filters using a field__lookup convention, plus a general search and an ordering parameter. Available filters vary by resource — the reference lists each endpoint's query parameters.

ParameterMeaningExample
searchFree-text search across a resource's searchable fields.?search=smith
orderingSort field; prefix with - for descending.?ordering=-last_visit
field__icontainsCase-insensitive substring match.?middle_name__icontains=ann
field__istartswith / __iexactPrefix / exact (case-insensitive) match.?last_name__istartswith=sm
field__gte / __lte / __gt / __ltRange comparisons (dates, numbers).?birth_date__gte=1990-01-01
field__inMatch any value in a comma-separated list.?treatments_or__in=1,2,3

Shaping the response: fields, omit & expand

Beyond filtering and search, most RxPhoto endpoints accept three parameters that control the shape of each result object. They keep payloads small and save you follow-up requests:

ParameterMeaningExample
fieldsReturn only the listed fields in each result.?fields=id,first_name,last_name
omitReturn everything except the listed fields.?omit=notes,history
expandInline a foreign-key's full object instead of just its ID — e.g. author returns the doctor object rather than a bare id.?expand=author
📎 Combine them to cut round-trips

Pair expand with fields to pull a related object inline while keeping the response lean — for example ?expand=author&fields=id,author. Each endpoint documents the foreign keys it can expand in the reference.

ℹ️ Incremental sync with date filters

To keep a local copy in sync, store the timestamp of your last run and filter on a date field with __gte (for example ?last_visit__gte=2026-06-01) to pull only records changed since then. Combine with pagination to page through the deltas.

Resource IDs

RxPhoto returns plain integer IDs for all resources — patients, images, bundles, forms, and so on. They appear directly in path parameters and response bodies:

// A patient response — IDs are integers:
{ "id": 12345, "first_name": "Jane", "last_name": "Smith", ... }

// Use the integer directly in the next call (note the trailing slash):
GET /api/v3/patient/12345/
📎 Different from PNE/VISH

PNE and VISH return opaque encrypted strings for IDs. If you're building an integration that touches both platforms, keep the ID types separate — don't mix integer RxPhoto IDs with encrypted PNE/VISH IDs.

Dates & times

Errors & status codes

RxPhoto uses standard HTTP status codes. The status line is the primary signal; a JSON body with a detail message may accompany errors.

CodeMeaningWhat to do
200 OKSuccessful read or update.Parse the body.
201 CreatedSuccessful create.Read the new record's id from the response body.
400 Bad RequestValidation failed — missing or invalid fields.Check the detail (or field errors) in the body; fix the payload.
401 UnauthorizedMissing or invalid token, or bad sign-in credentials.See 401/403 causes.
403 ForbiddenToken valid but not permitted, or account inactive/blocked.Confirm the account is active and has access to the resource.
404 Not FoundNo such record, or not visible to this token.Re-check the ID and that the trailing slash is present.
500 Server ErrorUnexpected server-side failure.Retry with backoff; if it persists, contact support.
📎 Build defensively

Always branch on the status code before parsing. A non-2xx response may carry a { "detail": "…" } body explaining the problem. Check for both 401 (not signed in / bad token) and 403 (signed in but not allowed) — RxPhoto distinguishes them.