Introducing eirly.dev, a home for developers building on Eirly

Pathology,
as an API.

Order blood tests for your patients, receive structured results and react to every step with signed webhooks. Built for the teams putting pathology inside their own product.

Production
api.eirly.health
Staging
api.staging.eirly.health
POST/webhooks/eirly200
{
  "eventName": "result.complete",
  "eventUuid": "98603d91-9d1b-4607-8ecb-705b33c66ef0",
  "version": "1.0",
  "data": {
    "uuid": "b69ff810-0823-41ee-8fd2-43ff01329fae"
  }
}
x-bgt-hmac-sha256: 9f2c…e41a

One order, end to end

Two calls from you. Every step in between, pushed to you.

  1. You call
    POST /v1/referrals

    You place the order for your patient.

  2. We send
    referral.created

    We confirm the referral exists.

  3. We send
    referral.issued

    The referral is ready for the patient to take to a pathology centre.

  4. We send
    result.partial_results

    The lab sends back the first results. This can fire more than once.

  5. We send
    result.complete

    Every result on the order is back.

  6. You call
    GET /v1/results/{uuid}

    You fetch the structured result, ready for your product.

terminal
# Exchange your client credentials for an access token
curl -X POST https://auth.staging.eirly.health/oauth/token \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -d grant_type=client_credentials

# Then call the API with it
curl https://api.staging.eirly.health/v1/tests \
  -H "Authorization: Bearer $ACCESS_TOKEN"
webhooks.ts
import crypto from 'node:crypto';

export function isFromEirly(rawBody: Buffer, signature?: string): boolean {
  // A SHA-256 HMAC is 64 hex characters. Reject anything else here:
  // timingSafeEqual throws on buffers of different lengths.
  if (!signature || !/^[0-9a-f]{64}$/i.test(signature)) return false;

  const expected = crypto
    .createHmac('sha256', process.env.EIRLY_SECRET_KEY!)
    .update(rawBody)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(signature, 'hex'),
  );
}

// signature = req.headers['x-bgt-hmac-sha256']
handler.ts
const event = JSON.parse(rawBody.toString());

switch (event.eventName) {
  case 'referral.issued':
    await notifyPatient(event.data.uuid);
    break;
  case 'result.partial_results':
  case 'result.complete':
    // Fetch the full, structured result
    await syncResult(event.data.uuid);
    break;
}

// Acknowledge fast; do the work in the background
res.status(200).end();
01

Place your first order

Create credentials in staging, get a token and call the API in under ten minutes.

Quickstart
02

React to every step

Signed webhooks for referrals and results, so your product updates the moment we do.

Webhooks
03

Keep up with changes

Product updates every month, and every API change field by field in the API changelog.

Changelog

Build against staging today.

Staging is a complete, separate environment with its own accounts and keys. Use a Stripe test card; nothing you do there charges a real one.

Get your staging keys