Skip to content
Browse developer documentation

Developer API · v1

CRM Contacts API

Synchronize leads and members from one RxApp affiliate into a CRM through a tenant-scoped, read-only API.

Last reviewed 25 September 2026

Overview

The Contacts API is intended for server-to-server CRM integrations. It exports contact and membership state but never accepts writes.

The API key determines the affiliate. Do not send an affiliate ID: a key can only read contacts belonging to its own tenant.

  • Production base URL: https://api.rxapp.io
  • API version: v1
  • Scope: contacts:read
  • Formats: JSON requests and responses; RFC 3339 UTC timestamps

Authentication

An RxApp affiliate owner or RxApp support provides a tenant-specific API key. Send it as a Bearer token on every request.

Keep the key in a server-side secret manager. Never place it in browser code, mobile bundles, source control, URLs, or application logs.

Authorization: Bearer rx_live_...

Quick start

Request the first page of contacts:

curl "https://api.rxapp.io/v1/contacts?limit=100" \
  -H "Authorization: Bearer $RXAPP_CRM_API_KEY"

Example response with fictional data:

{
  "items": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "contactType": "member",
      "firstName": "Alex",
      "lastName": "Example",
      "email": "alex@example.com",
      "membershipStatus": "active",
      "subscriptionPlanCode": "unlimited",
      "subscriptionPlanName": "Unlimited",
      "subscriptionStartedAt": "2026-09-01T00:00:00.000Z",
      "subscriptionEndsAt": null,
      "firstMembershipStartedAt": "2026-09-01T00:00:00.000Z",
      "version": 3,
      "updatedAt": "2026-09-25T12:00:00.000Z",
      "deletedAt": null
    }
  ],
  "page": {
    "nextCursor": null,
    "hasMore": false
  },
  "sync": {
    "watermark": "2026-09-25T12:05:00.000Z"
  }
}

Contact model

Use id as the external identity and version to ignore stale updates. Internal RxApp user IDs are never exposed.

FieldMeaning
idStable UUID for this contact.
contactTypelead or member. A converted member never becomes a lead again.
membershipStatusactive, pending, inactive, or null for a lead or tombstone.
subscription*Current membership plan and its start/end timestamps.
firstMembershipStartedAtEarliest qualifying membership start; never moves later.
versionMonotonically increasing contact version.
updatedAtTimestamp used by incremental synchronization.
deletedAtNon-null means tombstone; remove locally stored personal data.

Endpoints

Both public endpoints require a contacts:read key.

MethodPathPurpose
GET/v1/contactsList a stable page of contacts.
GET/v1/contacts/{contactId}Read one contact within the authenticated tenant.

List parameters

ParameterMeaning
updatedAfterExclusive RFC 3339 UTC checkpoint, for example 2026-09-25T12:05:00Z.
contactTypeOptional lead or member filter.
limitPage size from 1 through 500; default 100.
cursorOpaque continuation cursor. It must be the only query parameter.

Retrieve one contact by its exported UUID:

curl "https://api.rxapp.io/v1/contacts/11111111-1111-4111-8111-111111111111" \
  -H "Authorization: Bearer $RXAPP_CRM_API_KEY"

Synchronize safely

A watermark is a checkpoint for a completely processed page chain. Never advance it after a partial synchronization.

  1. Start with GET /v1/contacts and optional filters or the last committed updatedAfter watermark.
  2. Upsert every item by id. Ignore an item when its version is not newer than the locally stored version.
  3. If page.nextCursor is present, request only ?cursor=... and repeat until hasMore is false.
  4. Verify that sync.watermark remains identical on every page in the chain.
  5. Commit sync.watermark only after the final page has been processed successfully.
  6. Use the committed watermark as updatedAfter for the next run.
  7. If a cursor expires, discard it and restart from the last committed watermark.

Errors and rate limits

Error responses contain a stable code and X-Request-Id. Keep the request ID when contacting support.

StatusDeveloper action
400Correct the request or restart an invalid cursor from the last watermark.
401Stop and replace the missing, expired, or revoked API key.
403The key lacks the contacts:read scope.
404The contact does not exist within the authenticated tenant.
429Wait for Retry-After before retrying.
500/503Retry with bounded exponential backoff; report persistent failures with X-Request-Id.

Authenticated responses expose X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Limits are configured per key; do not assume a fixed value.

Downloads and support

The Postman collection contains only read-only requests. Set crmApiKey only as a local Current value and do not export a populated collection.

For access or integration support, email support@rxapp.io.