Appearance
Public API
Public endpoints at /public require no authentication. They power the patient-facing portal: report lookup, home sampling booking, and lab marketing pages.
Rate limiting
Sensitive endpoints use the auth rate limit policy:
| Endpoint | Limit behavior |
|---|---|
POST /public/reports/lookup | Throttled per IP |
POST /public/portal/{slug}/home-sampling | Throttled per IP |
Exceeded limits return HTTP 429.
Portal home
GET /public/portal/{slug}
Returns branding and configuration for a lab's public portal:
| Field | Description |
|---|---|
name, logoUrl | Lab branding |
slug | URL identifier |
isReadonly | Whether lab is in read-only mode |
features | Enabled portal features |
Returns 404 if slug not found.
Test search
GET /public/portal/{slug}/tests
| Parameter | Default | Description |
|---|---|---|
search | — | Filter test names |
pageSize | 30 | Max results |
Returns published tests with prices for the public catalog.
Report lookup
POST /public/reports/lookup
Request:
json
{
"slug": "my-lab",
"invoiceNumber": "10042",
"accessCode": "ABC123"
}Success: Report summary with test results (if verified and released).
Failure: 404 — Invalid invoice number or access code.
Access codes are printed on patient receipts or sent via SMS.
POST /public/reports/print-data
Returns formatted print layout data for browser printing:
json
{
"slug": "my-lab",
"invoiceNumber": "10042",
"accessCode": "ABC123"
}Home sampling
POST /public/portal/{slug}/home-sampling
Submit a home collection request:
| Field | Required | Description |
|---|---|---|
patientName | Yes | Patient full name |
phone | Yes | Contact number |
address | Yes | Collection address |
preferredDate | No | Requested date |
tests | No | Requested test names/IDs |
notes | No | Special instructions |
Staff process requests in the tenant portal under Home Sampling.
Web analytics
POST /public/analytics/visit
Records anonymous page visit events for marketing analytics (no PII).
Custom domains
When a custom domain is configured, public routes are also served on the branded hostname. The slug parameter still identifies the tenant internally.
Security considerations
| Control | Detail |
|---|---|
| Access codes | Required for report access; not guessable |
| No enumeration | Lookup failures are generic |
| HTTPS | Required in production |
| Read-only labs | Portal may show message; booking may be disabled |
Response format
Public routes use the standard ApiResponse<T> envelope where implemented:
json
{
"success": true,
"message": "Report retrieved successfully.",
"data": { }
}