Docs/Getting Started

Quickstart

Create a sandbox referral, read it back, receive a signed webhook, simulate a full care journey, and switch to live.

This guide takes you through the whole integration in the sandbox, from first request to go-live. In sandbox, no patient is ever contacted, no emails or WhatsApp messages are sent, and no commissions are earned, so you can experiment freely.

You need:

  • An approved partner account. Apply at https://partners.physioaroundme.com if you don't have one yet.
  • curl, Node.js 18 or later, or Python 3.8 or later with requests (pip install requests).

1. Get a sandbox API key

  1. Sign in to the Partner Portal and open Developers → API keys.
  2. Create a key in the sandbox environment and give it a name, such as quickstart. Sandbox keys start with sk_test_.
  3. Copy the key immediately. It's shown only once, because Rehabify stores only a hash of it. If you lose it, create a new key and revoke the old one.

Store the key in an environment variable. The examples below read it from REHABIFY_API_KEY:

export REHABIFY_API_KEY="sk_test_xxx"   # replace with your own sandbox key
Keep keys on your server
There are no shared or public sandbox keys. Every key belongs to your organisation. Never put an API key in browser code, a mobile app, a URL or a git repository. Partner endpoints don't send CORS headers, so browser calls fail anyway.

2. Create a referral

Send POST /partners/referrals. The patient phone number +2348000000003 is a sandbox magic number. It moves the referral through a full simulated care journey over about 35 seconds.

curl https://api.physioaroundme.com/v1/partners/referrals \
  -X POST \
  -H "Authorization: Bearer $REHABIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9b2f6c1e-4d7a-4c3b-8e5f-2a1d0c9b8e7f" \
  -d '{
    "partner_reference": "QUICKSTART-001",
    "patient": {
      "first_name": "Adeola",
      "last_name": "Balogun",
      "phone": "+2348000000003",
      "email": "adeola@example.com",
      "city": "Lagos",
      "state": "Lagos",
      "area": "Ikeja",
      "preferred_language": "en"
    },
    "clinical": {
      "condition": "Lower back pain",
      "notes": "Two weeks of pain after lifting. No red flags.",
      "priority": "standard",
      "recommended_sessions": 6,
      "referring_clinician": "Dr. Okafor"
    },
    "care": { "preferred_mode": "patient_choice", "preferred_contact_channel": "whatsapp" },
    "billing_mode": "patient_self_pay",
    "consent": {
      "granted": true,
      "method": "electronic",
      "captured_at": "2026-10-13T09:00:00.000Z",
      "privacy_notice_version": "2026-09-01"
    },
    "metadata": { "source": "quickstart" }
  }'

consent.granted is required and must be true. By setting it, you confirm the patient agreed to be contacted by Rehabify. clinical.notes is write-only: Rehabify's clinicians see it, but the API and webhooks never return it.

Idempotency
Sending the same request again with the same Idempotency-Key within 24 hours replays the original response, with the header Idempotent-Replayed: true, instead of creating a second referral. To create another referral, use a new Idempotency-Key and a new partner_reference. Reusing a partner_reference returns 409 duplicate_partner_reference.

3. Inspect the response

A successful call returns 201 Created with the full referral object:

201 Created
{
  "object": "referral",
  "id": "jd7f3k2m9x1q8w4e5r6t7y8u9i0o1p2a",
  "tracking_code": "RHB-4829173655",
  "partner_reference": "QUICKSTART-001",
  "environment": "sandbox",
  "status": "received",
  "patient": {
    "first_name": "Adeola",
    "last_name": "Balogun",
    "phone": "+2348000000003",
    "email": "adeola@example.com",
    "city": "Lagos",
    "state": "Lagos",
    "area": "Ikeja",
    "preferred_language": "en"
  },
  "clinical": {
    "condition": "Lower back pain",
    "priority": "standard",
    "recommended_sessions": 6,
    "referring_clinician": "Dr. Okafor"
  },
  "care": { "preferred_mode": "patient_choice", "preferred_contact_channel": "whatsapp" },
  "billing_mode": "patient_self_pay",
  "provider": null,
  "sessions": { "completed": 0, "total": 6, "last_session_at": null, "next_session_at": null },
  "links": {
    "tracking_url": "https://physioaroundme.com/track/RHB-4829173655",
    "whatsapp_intake_url": "https://wa.me/2348061525811?text=START%20RHB-4829173655"
  },
  "metadata": { "source": "quickstart" },
  "created_at": "2026-10-13T09:30:00.000Z",
  "updated_at": "2026-10-13T09:30:00.000Z"
}

Store id and tracking_code next to your own record. In live, give the patient links.whatsapp_intake_url. One tap opens a WhatsApp chat with Joy that's already linked to this referral, so the patient can start right away. links.tracking_url is a public status page that shows no personal data.

4. Read the referral back

You can fetch a referral by its id, its tracking_code or your own partner_reference. Wait about 40 seconds for the simulated journey to finish, then fetch it:

curl https://api.physioaroundme.com/v1/partners/referrals/QUICKSTART-001 \
  -H "Authorization: Bearer $REHABIFY_API_KEY"

By now status is completed and provider holds the simulated physiotherapist:

Relevant fields
{
  "status": "completed",
  "provider": { "name": "Sandbox Physiotherapist", "license_number": "SANDBOX-0001" }
}

5. Receive webhooks

Webhooks push every status change to your server, so you don't have to poll.

  1. Expose an HTTPS endpoint. It must use https:// and be publicly reachable. Private and internal hosts are rejected. For local development, use a tunnelling tool that gives you a public HTTPS URL.
  2. Register it. In the Partner Portal, go to Developers → Webhooks, set your sandbox endpoint URL, and copy the sandbox signing secret (whsec_…). Sandbox and live each have their own endpoint and secret, and events are never sent across environments.
  3. Verify signatures. Every delivery carries X-Rehabify-Signature: t=<unix seconds>,v1=<hex>. Here's a minimal Express receiver. Signature verification has Python, PHP and Go versions.
webhook-server.mjs
// npm install express
import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.REHABIFY_WEBHOOK_SECRET; // the sandbox whsec_… secret

function isValidSignature(rawBody, header) {
  if (!header || !Buffer.isBuffer(rawBody)) return false;
  let timestamp = null;
  const signatures = [];
  for (const part of header.split(",")) {
    const i = part.indexOf("=");
    if (i === -1) continue;
    const key = part.slice(0, i).trim();
    const value = part.slice(i + 1).trim();
    if (key === "t") timestamp = value;
    if (key === "v1") signatures.push(value);
  }
  if (!timestamp || !/^\d+$/.test(timestamp) || signatures.length === 0) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", SECRET).update(`${timestamp}.`).update(rawBody).digest();
  return signatures.some((sig) => {
    const received = Buffer.from(sig, "hex");
    return received.length === expected.length && crypto.timingSafeEqual(received, expected);
  });
}

// express.raw keeps the exact bytes that were signed. Register this route before any express.json().
app.post("/webhooks/rehabify", express.raw({ type: "application/json" }), (req, res) => {
  if (!isValidSignature(req.body, req.get("X-Rehabify-Signature"))) {
    return res.status(400).send("invalid signature");
  }
  const event = JSON.parse(req.body.toString("utf8"));
  console.log(event.id, event.type, event.data.referral.tracking_code);
  res.sendStatus(200); // acknowledge within 10 seconds; do slow work asynchronously
});

app.listen(3000, () => console.log("Listening on http://localhost:3000"));
  1. Send a test event. Use the portal's test button, or call the sandbox trigger endpoint:
curl https://api.physioaroundme.com/v1/sandbox/trigger-webhook \
  -X POST \
  -H "Authorization: Bearer $REHABIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "ping" }'
202 Accepted
{
  "object": "webhook_test",
  "event_id": "evt_01JA4V2K8M3N5P7Q9R1S3T5V7W",
  "type": "ping",
  "status": "queued",
  "endpoint": "https://example.com/webhooks/rehabify"
}
  1. Watch a real journey. Repeat step 2 with a new partner_reference and Idempotency-Key. Your endpoint receives referral.created, then an event for each status change (referral.contacted, referral.booked, referral.in_treatment and referral.completed), plus referral.provider_matched when the simulated physiotherapist is assigned. The event catalog shows every payload.

6. Simulate other scenarios

Each magic number triggers a different journey. Any other number stays received until you move it yourself.

PhoneBehaviour
+2348000000001→ contacted after ~5 s
+2348000000002→ contacted (~5 s) → provider_matched + booked (~15 s)
+2348000000003full journey: contacted (~5 s) → booked (~15 s) → in_treatment (~25 s) → completed (~35 s)
+2348000000004rejected immediately: 422 patient_ineligible (no referral created)
+2348000000005→ not_suitable after ~10 s
+2348000000006→ cancelled after ~10 s
any otherstays received — use the advance endpoint

To move a referral yourself, create one with any other number (for example +2348012345678), then call the sandbox-only advance endpoint. It fires the same webhooks a real transition would:

TRACKING_CODE="RHB-0123456789"   # replace with the tracking code (or id) of a sandbox referral that is still "received"
curl "https://api.physioaroundme.com/v1/sandbox/referrals/$TRACKING_CODE/advance" \
  -X POST \
  -H "Authorization: Bearer $REHABIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "contacted" }'

See Sandbox & testing for the full rules.

7. Go live

  1. In the Partner Portal, choose Request production access and work through the go-live checklist.
  2. Once Rehabify approves production access, create a sk_live_ key in Developers → API keys.
  3. Set your live webhook endpoint in Developers → Webhooks and store the live signing secret. It's different from your sandbox secret.
  4. Swap REHABIFY_API_KEY and REHABIFY_WEBHOOK_SECRET for their live values. The base URL stays the same.
Live means real patients
With a live key, Rehabify's care team and Joy contact every patient you refer, and magic phone numbers have no special behaviour. Only refer real patients who have agreed to be contacted.
Quickstart | Rehabify Docs | Physio Around Me by Rehabify Health