Skip to main content

REST API

The BGT REST API provides programmatic access to manage referrals, results, tests, and bundles. All API requests require authentication via OAuth 2.0.

New to the API?

See the Workflow overview first — it shows how these endpoints and webhooks fit together across referral ordering and results delivery.

Base URL: https://api.bloodygoodtests.com.au

Current Version: v1

Swagger Documentation

For interactive API documentation and testing, visit our Swagger Documentation

API Versioning

The API supports versioning through both URL paths and custom headers:

  • v1.0.0 (Default) - Blood tests only, single referral per request
  • v1.1.0 - Supports bundles, Medicare ordering, and multiple referrals per request

To use a specific version, include the Accept header:

Accept: application/vnd.bgt.v1.1.0+json

Authentication

All API endpoints require authentication. Include your access token in the Authorization header:

Authorization: Bearer YOUR_ACCESS_TOKEN

Timeouts

The ordering endpoint /referrals can take upwards of 10 seconds to complete, so please allow for this to avoid duplicate orders being sent if you have a retry strategy in place.

Core Resources

Referrals

Referrals represent test orders for patients. A referral contains patient information, requested tests, and metadata.

The referral payload will return an origin property, possible values are:

export enum ReferralOrigin {
ConsumerWebsite = 'CONSUMER_WEBSITE',
BundlePurchase = 'BUNDLE_PURCHASE',
Api = 'API',
StoreIntegration = 'STORE_INTEGRATION',
Unknown = 'UNKNOWN',
}

The referral status property progresses through the following values across the referral lifecycle:

export enum ReferralStatus {
PendingVerification = 'PENDING_VERIFICATION', // awaiting verification before issue
Created = 'CREATED', // created but not yet issued
Issued = 'ISSUED', // PDF generated and ready to deliver
ScheduledReissue = 'SCHEDULED_REISSUE', // a new PDF is being regenerated (e.g. after PATCH)
PartialResults = 'PARTIAL_RESULTS', // some but not all results returned
Complete = 'COMPLETE', // all results returned
InsufficientData = 'INSUFFICIENT_DATA', // unable to process due to missing data
Refunded = 'REFUNDED', // referral refunded
TestFailed = 'FAILED_TEST', // one or more tests failed at the lab
BillingFailed = 'BILLING_FAILED', // billing could not be completed
Transferred = 'TRANSFERRED', // referral transferred to another provider
}

Only referrals with status CREATED or ISSUED can be updated via PATCH. See Update Referral for details.

Create Referral

POST /v1/referrals

Creates a new referral for a patient.

Request Body:

{
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"addressLine2": null,
"postCode": "4000",
"city": "Brisbane",
"country": "Australia",
"state": "QLD"
},
"dob": "1980-01-01",
"gender": "male",
"phone": "0412345678",
"tests": ["tft", "free-testosterone"],
"metadata": {
"internalId": "1234"
},
"reference": "48213907",
"referenceNumber": "12345678",
"emailReferralToCustomer": true
}

Optional Fields:

FieldTypeDefaultDescription
emailReferralToCustomerbooleantrueControls whether BGT emails the referral PDF directly to the customer. Set to false if you want to deliver the referral to the customer yourself — when disabled, BGT will not send the referral email and you are responsible for getting it to the patient.

For v1.1.0 - Bundle Support:

{
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"postCode": "4000",
"city": "Brisbane",
"country": "Australia",
"state": "QLD"
},
"dob": "1980-01-01",
"gender": "male",
"phone": "0412345678",
"bundleId": "56ce2120-5480-4657-9e47-7ae4ecf9229b",
"metadata": {
"internalId": "1234"
}
}

Choosing between bundleId and tests:

On v1.1.0, a referral can be created from a pre-configured bundle, an ad-hoc list of tests, or both. At least one of tests, bundleId, or medicareTests must be provided — sending none will return a 400 error.

ProvidedBehaviour
tests onlyThe referral is created with exactly the tests you listed.
bundleId onlyThe referral is created with the full set of tests defined on that bundle. The bundle's productId / productName will be attached to the referral.
bundleId and testsThe referral includes every test in the bundle plus any additional tests you pass in tests. Use this when you want to extend a standard bundle on a per-patient basis (e.g. add vitamin-d to a "Men's Health" bundle). Duplicate tests are de-duplicated server-side.

Notes:

  • bundleId is only accepted on v1.1.0 and above. Sending a bundleId against v1.0.0 will return a 400 error directing you to upgrade the version header.
  • The response's tests array reflects the fully-resolved list of tests on the referral, regardless of whether they came from a bundle, the tests field, or both.

For v1.1.0 - Medicare ordering:

A single request can also order Medicare tests by passing medicareTests. These tests are ordered under a doctor's provider number and claimed against Medicare — they are not billed to your organisation. Commercial tests (tests / bundleId) continue to be billed exactly as before.

note
medicareTests is not a guarantee that the patient pays nothing

The field name says how the test is ordered — under Medicare, with the practitioner's provider number. Whether Medicare covers a given test in full is determined by the collecting laboratory and the patient's Medicare eligibility at the time of collection, and the patient may still be charged a gap or the full fee. Do not present these tests to your customers as guaranteed to be free.

When medicareTests is provided, the request produces two separate referrals — one commercial referral for tests/bundleId and one Medicare referral for medicareTests (issued on a Medicare request form). The response is therefore an array of referrals, and the customer receives a single email with both referral PDFs attached.

Prerequisite — the provider must be set up on the platform first

orderingPractitioner.providerNumber is not accepted as a free-form value. Before it can be used in an API request, the provider must be configured on the BGT platform:

  1. The provider number must be registered against the organisation that owns your API credentials. All API access is scoped to a single organisation, and the provider number you send must belong to a practitioner registered in that organisation. A provider number that isn't registered for your organisation is rejected with INVALID_PROVIDER_NUMBER.
  2. That practitioner must have a signature on file for the organisation. The signature is drawn and stored on the platform (Settings → Provider Numbers) — it cannot be supplied through the API — and it is what gets printed on the Medicare referral. If no signature is on file for the provider number, the request is rejected with MISSING_PROVIDER_SIGNATURE.

This is a one-time, per-practitioner, per-organisation setup done in the app, not via the API. See the Practitioners → Medicare guide for the full setup flow.

{
"firstName": "Jane",
"lastName": "Doe",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "456 Sample Street",
"postCode": "2000",
"city": "Sydney",
"country": "Australia",
"state": "NSW"
},
"dob": "1992-05-15",
"gender": "female",
"phone": "0498765432",
"tests": ["free-testosterone"],
"medicareTests": ["vitamin-d", "iron-studies"],
"orderingPractitioner": {
"name": "Dr Bill Smith",
"address": "123 Example St, Sydney NSW 2000",
"providerNumber": "2426621B"
},
"medicareCardNumber": "1234567890",
"dvaNumber": "QX123456",
"clinicalNotes": "Fatigue, ?anaemia",
"referenceNumber": "55667788"
}

Medicare fields:

FieldTypeRequiredDescription
medicareTestsstring[]Tests to order under Medicare using the practitioner's provider number. Produces a separate Medicare referral. Not a guarantee that the patient pays nothing.
orderingPractitionerobjectwhen medicareTests is presentThe ordering doctor: name, address, and providerNumber (all required). The providerNumber must be registered — with a signature — against your organisation (see prerequisite above).
medicareCardNumberstringwhen medicareTests is presentPatient's Medicare card number — 10 digits (optionally followed by a 1-digit IRN).
dvaNumberstringPatient's DVA file number, if applicable.
clinicalNotesstringThe ordering doctor's clinical notes for the Medicare referral. Kept separate from BGT's auto-generated clinical notes.

Notes:

  • Medicare ordering requires v1.1.0 and above. Sending medicareTests against v1.0.0 returns a 400 error directing you to upgrade the version header (the v1.0.0 single-referral response cannot represent two referrals).
  • The provider number must be registered against your organisation. The organisation is determined by the API credentials used for the request, and the providerNumber you send must belong to a practitioner registered in that organisation. If it isn't, the request is rejected with INVALID_PROVIDER_NUMBER.
  • A signature must be on file for that provider number. Signatures are captured on the platform (Settings → Provider Numbers), not via the API. A provider number with no signature on file is rejected with MISSING_PROVIDER_SIGNATURE. Omitting orderingPractitioner entirely returns MISSING_PROVIDER_NUMBER.
  • orderingPractitioner.providerNumber must also be a valid 8-character Medicare provider number, and medicareCardNumber must be 10 digits (optionally + IRN). Malformed identifiers return a 400.
  • Only pathology (blood) tests can be ordered under Medicare. Including a non-eligible test in medicareTests is rejected with INVALID_MEDICARE_TEST.
  • The same test id may appear in both tests and medicareTests — ordering the same test as both commercial and Medicare is valid and yields it on both referrals. Duplicates within a single list are de-duplicated.
  • You may send medicareTests on its own (no tests/bundleId) to create a Medicare referral only.
  • Result routing is advisory, not a prerequisite. The Medicare referral is always created regardless of whether the provider number has result routing configured. The Medicare referral in the response carries a routingMessage describing whether (and from which labs) the practitioner's Medicare results will route back to them automatically, and — when routing isn't set up — how to configure it. See the routingMessage field in the response table below.

Response (200 OK):

{
"uuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "ISSUED",
"object": "referral",
"tests": ["tft", "free-testosterone"],
"metadata": {
"internalId": "1234"
},
"productId": null,
"productName": null,
"origin": "API",
"person": {
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"addressLine2": null,
"postCode": "4000",
"city": "Brisbane",
"country": "Australia",
"state": "QLD"
},
"phone": "0412345678",
"dob": "1980-01-01",
"gender": "male"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "12345678",
"referralAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaWxlVXVpZCI6IjJhNGRkYjALTk5MItNDUxMy1iMTAxLTMzMjBmZmYzMzAwMSIsInByb2ZpbGVVdWlkIjoiMTQxZjQ5NTgtjYzJkYi00NDY1LIwMTEtODc3MmZmZjQzMzU3IiwicmFuZG9tVmsdWUiOiJBTHJrOXNYM01iWnFXcGc4UFNRdGZmS3Fd6dGRzZ24iLCJvcmdhbmljzYXRpb25VdWlkIjoiNWQ0NDkxOTQtYzVjMS00DUzLWIyNjTQtZGRhNzg0MjdkZjllIiwiZm9y2VEb3dubG9hZCI6dHJ1ZSwiaWF0IjjoxNzc5NDI2MjExLCJleHAiOjdE3Nzk0MjcxMTF9.x7Hj2vP9aQmLZc5dRngK4tUyB1eF6oI3wJxN8sVrTYg",
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T05:29:09.385Z",
"deletedAt": null,
"resultsUuid": null,
"medicare": false,
"orderingPractitioner": null,
"medicareCardNumber": null,
"dvaNumber": null,
"orderingPractitionerClinicalNotes": null,
"routingMessage": null
}

Notable response fields:

FieldTypeDescription
referencestringOur unique reference for this referral (8 digits). Distinct from referenceNumber, which is the value you supplied on create.
referralAttachmentstring (url) | nullSigned URL to the referral PDF. null until the PDF has been generated (e.g. while status is CREATED or SCHEDULED_REISSUE), and null for deleted referrals. URLs are time-limited — re-fetch the referral to get a fresh URL.
updatedAtstring (ISO 8601)Time the referral record was last modified. Updated whenever the referral status changes or fields are edited via PATCH.
deletedAtstring (ISO 8601) | nullSet when the referral has been soft-deleted via DELETE; null otherwise.
emailSentAtstring (ISO 8601) | nullTime the referral email was dispatched to the customer. null if emailReferralToCustomer was false, or before delivery has occurred.
resultsUuidstring (uuid) | nullUUID of the associated result once results are available (i.e. once status reaches PARTIAL_RESULTS or COMPLETE).
medicarebooleantrue if this referral was ordered under Medicare, false for a commercial referral. Not a statement about what the patient was ultimately charged.
orderingPractitionerobject | nullThe ordering doctor (name, address, providerNumber). Present on Medicare referrals only.
medicareCardNumberstring | nullPatient's Medicare card number. Present on Medicare referrals only.
dvaNumberstring | nullPatient's DVA file number. Present on Medicare referrals only.
orderingPractitionerClinicalNotesstring | nullThe ordering doctor's clinical notes. Present on Medicare referrals only.
routingMessagestring | nullAdvisory, human-readable summary of whether (and from which labs) the Medicare results will route back to the practitioner automatically. Advisory only — never blocks the order. Populated on the Medicare referral returned from Create; null on commercial referrals and on all other endpoints.

Note: When a request includes medicareTests, this endpoint returns an array of referrals (one commercial, one Medicare) rather than a single object.

Response (200 OK) — Medicare request (array):

[
{
"uuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "ISSUED",
"object": "referral",
"tests": ["free-testosterone"],
"metadata": null,
"productId": null,
"productName": null,
"origin": "API",
"person": {
"firstName": "Jane",
"lastName": "Doe",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "456 Sample Street",
"addressLine2": null,
"postCode": "2000",
"city": "Sydney",
"country": "Australia",
"state": "NSW"
},
"phone": "0498765432",
"dob": "1992-05-15",
"gender": "female"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "55667788",
"referralAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T05:29:09.385Z",
"deletedAt": null,
"resultsUuid": null,
"medicare": false,
"orderingPractitioner": null,
"medicareCardNumber": null,
"dvaNumber": null,
"orderingPractitionerClinicalNotes": null,
"routingMessage": null
},
{
"uuid": "9b1f3c7a-2e54-4d0b-8a61-1c2d3e4f5a6b",
"status": "ISSUED",
"object": "referral",
"tests": ["vitamin-d", "iron-studies"],
"metadata": null,
"productId": null,
"productName": null,
"origin": "API",
"person": {
"firstName": "Jane",
"lastName": "Doe",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "456 Sample Street",
"addressLine2": null,
"postCode": "2000",
"city": "Sydney",
"country": "Australia",
"state": "NSW"
},
"phone": "0498765432",
"dob": "1992-05-15",
"gender": "female"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "55667788",
"referralAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T05:29:09.385Z",
"deletedAt": null,
"resultsUuid": null,
"medicare": true,
"orderingPractitioner": {
"name": "Dr Bill Smith",
"address": "123 Example St, Sydney NSW 2000",
"providerNumber": "2426621B"
},
"medicareCardNumber": "1234567890",
"dvaNumber": "QX123456",
"orderingPractitionerClinicalNotes": "Fatigue, ?anaemia",
"routingMessage": "Result routing isn't set up for provider number 2426621B, so Medicare results won't route back to you automatically. Set up result routing at https://app.bloodygoodtests.com.au/org/your-org/settings/result-routing."
}
]

Get Referral

GET /v1/referrals/{uuid}

Retrieves a specific referral by UUID.

Response (200 OK): Same structure as Create Referral response

List Referrals

GET /v1/referrals

Returns all referrals for your organisation with pagination support.

Query Parameters:

  • count (integer, optional) - Number of results to return (max 20, default 20)
  • cursor (string, optional) - Cursor for pagination
  • sort (string, optional) - Sort order: asc or desc (default: asc)

Response (200 OK):

{
"cursor": {
"cursor": "MjAyNC0wNi0wNFQxMjo1OTowMS44MDJafGNyZWF0ZWRBdHxhc2M=",
"count": 20,
"resultCount": 5
},
"referrals": [
{
"uuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "COMPLETE",
"object": "referral",
"tests": ["tft", "free-testosterone"],
"metadata": {
"internalId": "1234"
},
"productId": "prod_abc123",
"productName": "Comprehensive Health Check",
"origin": "API",
"person": {
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"postCode": "4000",
"city": "Brisbane",
"state": "QLD"
},
"phone": "0412345678",
"dob": "1980-01-01",
"gender": "male"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "12345678",
"referralAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T05:29:09.385Z",
"deletedAt": null,
"resultsUuid": "d9d820a4-72e1-41bc-9fac-ffb23f18dfb4",
"medicare": false,
"orderingPractitioner": null,
"medicareCardNumber": null,
"dvaNumber": null,
"orderingPractitionerClinicalNotes": null,
"routingMessage": null
}
]
}

Update Referral

PATCH /v1/referrals/{uuid}

Updates person details and/or metadata on an existing referral. A new referral PDF will be generated after the update.

Status Restriction

Only referrals with a status of CREATED or ISSUED can be updated. Attempting to update a referral with any other status (e.g. COMPLETE, PARTIAL_RESULTS, REFUNDED) will return an error.

All fields are optional — only the fields you include in the request body will be updated. Omitted fields remain unchanged.

Request Body:

FieldTypeDescription
firstNamestringPatient's first name (min 2 chars)
lastNamestringPatient's last name (min 2 chars)
emailstringPatient's email address
dobstringDate of birth (format: YYYY-MM-DD)
genderstringmale or female
phonestringPhone number (min 6 chars)
addressobjectAddress object (see Create Referral)
metadataobjectKey-value pairs (see Metadata Merging)

Metadata Merging:

Metadata is merged with the existing metadata on the referral rather than replaced. To remove a key, set its value to null:

{
"metadata": {
"newKey": "new-value",
"existingKey": "updated-value",
"keyToRemove": null
}
}

Example — update name and email:

{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com"
}

Example — update address:

{
"address": {
"addressLine1": "456 New Street",
"addressLine2": "Unit 3",
"postCode": "2000",
"city": "Sydney",
"country": "Australia",
"state": "NSW"
}
}

Response (200 OK):

{
"uuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "SCHEDULED_REISSUE",
"object": "referral",
"tests": ["tft", "free-testosterone"],
"metadata": {
"internalId": "5678"
},
"productId": "prod_abc123",
"productName": "Comprehensive Health Check",
"origin": "API",
"person": {
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"address": {
"addressLine1": "123 Example Way",
"addressLine2": null,
"postCode": "4000",
"city": "Brisbane",
"country": "Australia",
"state": "QLD"
},
"phone": "0412345678",
"dob": "1980-01-01",
"gender": "male"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "12345678",
"referralAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T06:15:00.000Z",
"deletedAt": null,
"resultsUuid": null,
"medicare": false,
"orderingPractitioner": null,
"medicareCardNumber": null,
"dvaNumber": null,
"orderingPractitionerClinicalNotes": null,
"routingMessage": null
}
tip

After a successful update, the referral status will change to SCHEDULED_REISSUE while a new PDF is generated. Once the PDF is ready, the status will return to ISSUED.

Delete Referral

DELETE /v1/referrals/{uuid}

Soft-deletes a referral. The referral will be marked as deleted but not permanently removed. The referralAttachment URL is cleared on deletion.

Response (200 OK):

{
"uuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "COMPLETE",
"object": "referral",
"tests": ["tft", "free-testosterone"],
"metadata": {
"internalId": "1234"
},
"productId": "prod_abc123",
"productName": "Comprehensive Health Check",
"origin": "API",
"person": {
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"addressLine2": null,
"postCode": "4000",
"city": "Brisbane",
"country": "Australia",
"state": "QLD"
},
"phone": "0412345678",
"dob": "1980-01-01",
"gender": "male"
},
"referralType": "blood",
"reference": "48213907",
"referenceNumber": "12345678",
"referralAttachment": null,
"emailSentAt": "2024-06-04T05:29:09.385Z",
"createdAt": "2024-06-04T05:29:06.508Z",
"updatedAt": "2024-06-04T07:00:00.000Z",
"deletedAt": "2024-06-04T07:00:00.000Z",
"resultsUuid": "d9d820a4-72e1-41bc-9fac-ffb23f18dfb4",
"medicare": false,
"orderingPractitioner": null,
"medicareCardNumber": null,
"dvaNumber": null,
"orderingPractitionerClinicalNotes": null,
"routingMessage": null
}

Simulate Results (Staging Only)

PUT /v1/referrals/{uuid}
Staging only

This endpoint is only available in the staging environment and will return 404 in production. It is intended for integrators testing end-to-end flows without waiting for a real lab to return results.

Generates a set of random dummy results for the referral, allowing you to exercise the result-related endpoints, webhooks, and your downstream handling code without involving a real pathology lab.

Query Parameters:

  • partial (flag, optional) — if present (e.g. ?partial), only a partial set of results is generated and the referral transitions to PARTIAL_RESULTS instead of COMPLETE. Useful for testing how your integration handles PARTIAL_RESULTSCOMPLETE transitions and the associated webhooks.

Examples:

PUT /v1/referrals/254fa374-6d05-4a41-bfd8-254ba2039049
PUT /v1/referrals/254fa374-6d05-4a41-bfd8-254ba2039049?partial

Response (200 OK): Returns the updated referral. Once results have been generated, resultsUuid will be populated and the corresponding result can be fetched via GET /v1/results/{resultsUuid}.

Results

Results contain biomarker data and test outcomes for completed referrals.

Get Result

GET /v1/results/{uuid}

Retrieves detailed results for a specific result UUID.

Response (200 OK):

{
"uuid": "d9d820a4-72e1-41bc-9fac-ffb23f18dfb4",
"referralUuid": "254fa374-6d05-4a41-bfd8-254ba2039049",
"status": "COMPLETE",
"object": "result",
"reference": "48213907",
"referenceNumber": "12345678",
"productId": "prod_abc123",
"productName": "Comprehensive Health Check",
"origin": "API",
"resultAttachment": "https://api.bloodygoodtests.com.au/download/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaWxlVXVpZCI6IjNiNmVjYzA4LTE0gmEtNDk4Ni1iYjYzLTdkgDJiZGZjNzU3ZSIsInByb2ZpbGVVdWlkIjoiMTQxZjQ5NTgtYzJkYi00NDY1LWIwMTEtODc3MmZmZjQzMzU3IiwicmFuZG9tVmFsdWUiOiJJWk5vN2VKOEFmcWM4bFpjS0lRcmt3YXlzZ1o2RjMiLCJvcmdhbmlzYXRpb25VdWlkIjoiNWQ0NDkxOTQtYzVjMS00NDUgLWIyNTQtZGRhNzg0MjdkZjllIiwiZm9yY2VEb3dubG9hZCI6dHJ1ZSwiaWF0IjoxNzc5NDI2MjExLCJleHAiOjE3Nzk0MjcxMTF9.A5jHeOt7W71IqN5sbxnK7jsYiZ9LO6NB7wK42F5aTCw",
"createdAt": "2024-06-04T05:30:08.699Z",
"updatedAt": "2024-06-04T05:30:08.699Z",
"deletedAt": null,
"resultDate": "2024-05-29T15:29:00.000Z",
"reviewedBy": null,
"person": {
"firstName": "John",
"lastName": "Vein",
"email": "john.vein@bloodygoodtests.com.au",
"address": {
"addressLine1": "123 Example Way",
"postCode": "4000",
"city": "Brisbane",
"state": "QLD"
},
"phone": "0412345678",
"dob": "1980-01-01",
"gender": "male"
},
"metadata": {
"internalId": "1234"
},
"biomarkerSummary": {
"normal": 18,
"abnormal": 2,
"critical": 0,
"total": 20
},
"biomarkers": [
{
"commonName": "Active Vitamin B12",
"description": "Active Vitamin B12 (Holotranscobalamin) is the bioavailable portion...",
"formattedValue": "2 pmol/L",
"id": "active-vitamin-b12",
"isAbnormal": false,
"name": "Active Vitamin B12",
"object": "biomarker",
"unit": "pmol/L",
"sampleType": "serum",
"notes": "Sample was collected fasting. Serum separator tube used.",
"category": {
"id": "vitamins-and-minerals",
"name": "Vitamins & Minerals",
"description": "Vitamins and minerals are important for the body...",
"object": "biomarker-category"
},
"valueType": "numeric",
"value": "2",
"subValueType": null,
"refIntervalHigh": 4,
"refIntervalLow": 1,
"additionalRanges": null
}
]
}

Notable fields:

FieldTypeDescription
referralUuidstring (uuid)UUID of the referral this result was generated from.
resultAttachmentstring (url) | nullSigned URL to the result PDF. May be null if a PDF has not yet been generated. URLs are time-limited — re-fetch the result to obtain a fresh URL.
originstring | nullWhere the originating referral came from (e.g. API).
createdAtstring (ISO 8601)Time the result record was created.
deletedAtstring (ISO 8601) | nullSet if the result has been soft-deleted.
biomarkerSummaryobject | nullAggregated counts of normal, abnormal, critical, and total biomarkers on the result.
biomarkers[].sampleTypestring | nullThe sample type used for this biomarker (e.g. serum, whole-blood).
biomarkers[].notesstring | nullLab-provided notes for the individual biomarker, if any.
biomarkers[].additionalRangesarray | nullAdditional reference ranges for numeric biomarkers (e.g. menstrual cycle-phase bands for female hormones, or lipid risk targets). null for string-valued biomarkers, and null (or omitted) on numeric biomarkers that have no extra ranges. See below for the entry shape and examples.

additionalRanges entry shape:

Each entry in additionalRanges describes one alternative reference interval that applies in a specific context (cycle phase, lipid risk target, etc.). The biomarker's top-level refIntervalLow / refIntervalHigh remain the default range — additionalRanges are supplementary and consumers should continue to use the primary range for the default in/out-of-range determination.

FieldTypeDescription
idstringIdentifier for the range (e.g. cycle phase key, "high-risk").
namestringHuman-readable name for the range (e.g. "Follicular phase", "Lipid risk target").
categorystringCategory the range belongs to (e.g. "female-hormone", "lipid-risk-target").
lowRangenumber | nullLower bound of the range. null means open-ended on the low side (e.g. < highRange).
highRangenumber | nullUpper bound of the range. null means open-ended on the high side (e.g. > lowRange).

Example — female sex hormone with cycle-phase ranges (e.g. Oestradiol, FSH, LH, Progesterone):

For female hormone biomarkers, the lab cannot determine the patient's cycle phase, so the primary refIntervalLow / refIntervalHigh are typically null and all phase-specific ranges are returned via additionalRanges:

{
"refIntervalLow": null,
"refIntervalHigh": null,
"additionalRanges": [
{ "id": "follicular", "name": "Follicular phase", "category": "female-hormone", "lowRange": 46, "highRange": 607 },
{ "id": "ovulation", "name": "Ovulation", "category": "female-hormone", "lowRange": 315, "highRange": 1828 },
{ "id": "luteal", "name": "Luteal phase", "category": "female-hormone", "lowRange": 161, "highRange": 774 },
{ "id": "post-menopause", "name": "Post-menopausal", "category": "female-hormone", "lowRange": null, "highRange": 201 }
]
}

Example — lipid risk targets (e.g. Total Cholesterol, LDL, HDL, Triglycerides, Non-HDL):

Some lipid panels include a separate cardiovascular risk target (e.g. NVDPA high-risk targets) alongside the standard reference range. The standard range is reported as the primary refIntervalLow / refIntervalHigh, and the risk target is exposed as a "high-risk" entry under additionalRanges:

LDL Cholesterol — the primary range is the lab's standard reference; the additional entry is the high-cardiovascular-risk target (< 2.0 mmol/L):

{
"refIntervalLow": null,
"refIntervalHigh": 3.4,
"additionalRanges": [
{ "id": "high-risk", "name": "Lipid risk target", "category": "lipid-risk-target", "lowRange": null, "highRange": 2.0 }
]
}

HDL Cholesterol — the high-risk target is a minimum (> 1.0 mmol/L), so highRange is null:

{
"refIntervalLow": 1.0,
"refIntervalHigh": null,
"additionalRanges": [
{ "id": "high-risk", "name": "Lipid risk target", "category": "lipid-risk-target", "lowRange": 1.0, "highRange": null }
]
}

Most biomarkers will return "additionalRanges": null — only those with clinically meaningful contextual ranges (female sex hormones, lipid risk targets) populate the array.

List Results

GET /v1/results

Returns all results for your organisation with pagination support.

Query Parameters:

  • count (integer, optional) - Number of results to return (max 20, default 20)
  • cursor (string, optional) - Cursor for pagination
  • sort (string, optional) - Sort order: asc or desc (default: asc)

Response (200 OK): Array of results with cursor metadata

Tests

Tests represent available blood tests and their pricing.

List Tests

GET /v1/tests

Returns all available tests for your organisation.

Response (200 OK):

[
{
"id": "cortisol",
"name": "Cortisol",
"shortName": "Cortisol",
"price": 356,
"object": "test",
"turnAroundTimeAverage": {
"maximumDays": 7,
"minimumDays": 7,
"object": "turnaroundTime"
},
"turnAroundTimes": [
{
"maximumDays": null,
"minimumDays": null,
"providerId": "4cyte",
"providerName": "4Cyte Pathology",
"object": "providerTurnaroundTime"
}
]
}
]

Notes:

  • Prices are in cents (divide by 100 for dollar amount)
  • v1.0.0 returns blood tests only
  • v1.1.0 returns all available test types

Bundles

Bundles are pre-configured groups of tests that can be purchased together (v1.1.0+ only).

List Bundles

GET /v1/bundles

Headers Required:

Accept: application/vnd.bgt.v1.1.0+json

Query Parameters:

  • count (integer, optional) - Number of results to return (max 20, default 20)
  • cursor (string, optional) - Cursor for pagination
  • sort (string, optional) - Sort order: asc or desc (default: asc)

Response (200 OK):

{
"cursor": {
"cursor": "MjAyNC0wNi0wNFQxMjo1OTowMS44MDJafGNyZWF0ZWRBdHxhc2M=",
"count": 20,
"resultCount": 5
},
"bundles": [
{
"id": "254fa374-6d05-4a41-bfd8-254ba2039049",
"name": "Comprehensive Health Panel",
"object": "bundle",
"tests": [
{
"id": "tft",
"name": "Thyroid Function Test",
"object": "test"
}
],
"createdAt": "2024-06-04T05:29:06.508Z"
}
]
}

Common Response Codes

CodeDescription
200Success
400Bad Request - Invalid parameters or payload
401Unauthorized - Missing or invalid access token
404Not Found - Resource does not exist
500Internal Server Error

Error Response Format

All error responses follow this structure:

{
"error": true,
"code": "ERROR_CODE",
"message": "Human readable error message",
"errorList": ["Additional error details"]
}

Common Error Codes

CodeMessage
MISSING_AUTHORIZATION_HEADERMissing Authorization header
INVALID_JWTInvalid access token
INVALID_JWT_SIGNATUREInvalid JWT Signature
INVALID_PARAMETERThe parameter provided is invalid
INVALID_PAYLOADThe payload provided is invalid
REFERRAL_NOT_FOUNDUnable to find the specified referral
RESULT_NOT_FOUNDUnable to find the specified result
MISSING_PROVIDER_NUMBERAn ordering practitioner is required for Medicare tests
INVALID_PROVIDER_NUMBERProvider number is not registered for your organisation (or is malformed)
MISSING_PROVIDER_SIGNATURENo Medicare signature on file for the provided provider number
INVALID_MEDICARE_TESTOnly pathology (blood) tests can be ordered under Medicare
INVALID_MEDICARE_NUMBERThe patient's Medicare card number is missing or invalid

Pagination

List endpoints support cursor-based pagination:

  1. Make initial request without cursor
  2. Response includes cursor.cursor value
  3. Pass this value as cursor query parameter in next request
  4. Repeat until cursor.resultCount is less than requested count

Metadata

Custom metadata can be attached to referrals for correlation purposes:

{
"metadata": {
"internalId": "your-internal-id",
"customField": "custom-value"
}
}

Metadata is returned with the referral and results objects, allowing you to correlate BGT records with your internal systems.

Rate Limiting

API rate limits apply per organisation. Contact BGT if you require higher limits.

Support

For API support:

  • Review the Swagger Documentation for interactive examples
  • See Webhooks for real-time notifications
  • Contact the BGT API team for integration assistance