Documentation

Platform overview, getting started, the API reference, integrations, security and operations. Sections marked Planned describe capability that is not yet available.

Introduction

What is ArayaThrust?

ArayaThrust is a cloud clinic management platform built for Nigerian healthcare facilities. It is sold as a subscription in four tiers, billed in naira, with pricing based on facility size rather than patient volume.

What this documentation covers

This documentation describes the parts of ArayaThrust that are implemented and deployed today: the public website, the subscription and onboarding system, and the API that supports them. Clinical modules are described on the Features pages as product capability and are marked Planned here until they ship, so that nothing on this page can be mistaken for an available integration point.

Core capabilities

The capabilities below are live. Each links to the section that documents it.

  • Email address verification by one-time code, valid for 10 minutes.
  • Subscription checkout in naira through Paystack, covering card, bank transfer, USSD and QR.
  • Server-side payment confirmation by signed webhook, independent of the browser.
  • Automated VAT-itemised receipts delivered over Amazon SES.
  • Single-use account handoff from a confirmed payment to the customer portal.
  • Contact, demo and trial enquiry delivery to the team inbox.

Clinical modulesPlanned

Electronic records, SOAP notes, pharmacy, laboratory and LIMS, HMO interconnectivity and multi-branch management are the subject of the subscription tiers and appear throughout the Features and Pricing pages. They are not yet documented here because no implementation exists in this repository to document.

Why they are listed anyway

Listing them as Planned is deliberate. A technical evaluator comparing the tier table against this documentation should be able to see exactly which capabilities are purchasable commitments and which are callable today.

Key terminology

TermMeaning
TierOne of Starter, Professional, Enterprise or Chain. Determines price and feature set.
Setup feeA one-time charge of 1x, 2x or 3x the monthly price, chosen at checkout.
ReferenceThe unique identifier for a payment attempt. Generated client-side, confirmed server-side.
Handoff tokenA single-use opaque key minted after a payment is verified, exchanged by the portal for subscriber details.
Verification codeA six-digit code emailed during signup. Expires after 10 minutes.

Getting Started

Prerequisites

  • An email address you can receive mail at — receipts and the account setup link are delivered there.
  • A Nigerian payment method accepted by Paystack: card, bank transfer, USSD or QR.
  • A modern browser. Checkout opens Paystack in an embedded frame, so content blockers that strip third-party frames must allow it.

Account registration

Registration begins on the signup page. The form collects your name, facility, email, phone and role, then sends a six-digit code to the address you entered.

If the backend cannot deliver that code, the form skips verification and continues to plan selection rather than trapping you on a step that cannot complete.

Code lifetime

Codes expire 10 minutes after they are issued and each code records its own attempt count. Request a fresh code rather than retrying an expired one.

First-use walkthrough

After verification you choose a tier and billing cycle, which starts a 30-day trial recorded in your browser. Converting to a paid subscription happens at checkout, and on success the platform issues a single-use link that creates your portal account with the purchased plan already applied.

The Quick Start guide walks this end to end with the exact screens in order.

Platform Configuration

Administration, workspaces and rolesPlanned

Administrative settings, organisation and workspace management, user and role management, access permissions and environment configuration are functions of the customer portal at portal.arayathrust.com. The portal is a separate application and is not part of this repository, so its configuration surface is not documented here.

What is defined today

One piece of configuration is real and specified: the role captured at signup (Doctor, Administrator or CMD) and the purchased tier both travel to the portal inside the handoff token. The portal is the authority on what either grants.

API

API overview

ArayaThrust exposes a small HTTP API that backs signup verification, transactional email, payment confirmation and the portal account handoff. It is a transactional API, not a data API: there are no read endpoints for clinical or customer records.

  • Every route is POST. A GET returns 404 because no GET route is registered.
  • Requests and responses are JSON, with Content-Type: application/json.
  • The base URL differs per environment and is supplied to the site at build time. It appears below as {API_BASE}.

CORS

Browser calls are accepted only from configured origins, limited to the POST and OPTIONS methods and the content-type header, with preflight cached for one hour. A call from an unlisted origin is rejected by the browser.

Authentication and authorisation

The API uses three different trust models, chosen per route by what the caller can prove.

ModelRoutesHow the caller is trusted
Open/forms, /emails/welcome, /auth/verify/request, /auth/verify/confirm, /auth/handoff/issueNo credential. These are called by the browser, so they are rate limited and return nothing that is not already known to the caller.
Signed payload/paystack/webhookAn HMAC SHA-512 signature over the raw body, verified against the Paystack secret in constant time. The charge is then re-confirmed directly with Paystack before anything is acted on.
Shared key/auth/handoff/verifyAn x-api-key header. Server-side callers only — the key must never reach a browser.

Entitlement never comes from the client

No endpoint accepts a plan, price or payment status from the caller. A subscription becomes active only when Paystack confirms the charge to the webhook, which is why /auth/handoff/issue returns ready:false until that has happened.

Endpoints

Method and pathPurpose
POST /formsDeliver a contact, demo or trial enquiry to the team inbox.
POST /emails/welcomeSend the trial welcome email.
POST /auth/verify/requestEmail a six-digit verification code.
POST /auth/verify/confirmValidate a six-digit code.
POST /auth/handoff/issueExchange a payment reference for the account setup link.
POST /auth/handoff/verifyServer-side only. Exchange a handoff token for subscriber details and burn it.
POST /paystack/webhookReceive Paystack charge events. Called by Paystack, not by you.

Request and response examples

Request a verification code
curl -X POST {API_BASE}/auth/verify/request \
  -H "Content-Type: application/json" \
  -d '{"email":"dr.okonkwo@clinic.ng","name":"Dr. Okonkwo"}'
Confirm a code
curl -X POST {API_BASE}/auth/verify/confirm \
  -H "Content-Type: application/json" \
  -d '{"email":"dr.okonkwo@clinic.ng","code":"482913"}'

# 200 { "verified": true }
# 200 { "verified": false }   incorrect or expired
Exchange a payment reference for the setup link
curl -X POST {API_BASE}/auth/handoff/issue \
  -H "Content-Type: application/json" \
  -d '{"reference":"AT-MG3K2P-9F1C4B7E2A"}'

# 200 { "ready": false }
#   the webhook has not confirmed this charge yet — poll, or fall back to email
# 200 { "ready": true, "token": "…", "setupUrl": "https://portal.arayathrust.com/auth/login?token=…" }

ready:false is not an error

A confirmed charge and a confirmed webhook are separate events, and a bank transfer can settle minutes apart from the browser returning. Treat ready:false as 'not yet', poll briefly, and fall back to the emailed link rather than showing a failure.

Error handling

StatusMeaningWhat to do
400Malformed JSON, or a required field missing or invalid.Fix the request. Retrying unchanged will not help.
401Signature or shared key rejected.Check that the signing secret or x-api-key matches the environment you are calling.
404No route matches the method and path.Confirm you are sending POST — every route is POST only.
429Throttled.Back off and retry. See Rate limits.
502A downstream call failed — Paystack, DynamoDB or SES.Transient. Retry with backoff; the webhook is built to be retried safely.

Errors return a JSON body with an error key, for example {"error":"invalid_json"}. The webhook is the exception: it answers Paystack in plain text, because Paystack reads only the status code.

Rate limits

The API is throttled at the gateway at 10 requests per second sustained, with a burst allowance of 20. The limit is shared across all routes and all callers, not allocated per client. Exceeding it returns 429.

Sizing

These limits suit the interactive flows the API serves — a signup, a checkout, a webhook delivery. They are not sized for bulk or batch traffic. If you need higher throughput, raise it before building against the API rather than after.

Versioning

No version negotiation today

Paths carry no version segment and the API does not read an API-version header. There is one deployed version of each route. Treat the shapes above as current rather than contractual, and if you build an integration that must survive change, agree a contract with us first.

Integrations

Paystack

Paystack is the payment processor for all subscription billing, in naira, across card, bank transfer, USSD and QR.

The browser opens Paystack with a public key and a generated reference. It never decides whether payment succeeded. Paystack signs a charge event to the webhook, which verifies the signature, re-confirms the charge against the Paystack API, and only then records it and emails a receipt.

Because the browser chooses the amount it asks Paystack to charge, the webhook also compares the amount actually paid against every legitimate total for the claimed tier and billing cycle. A mismatch still issues the receipt and the setup link, and flags the discrepancy to the team for review.

Webhooks

One inbound webhook is implemented: POST /paystack/webhook, which handles charge.success and acknowledges every other event without acting on it.

  • The signature is an HMAC SHA-512 of the raw request body, compared in constant time.
  • Each payment reference is claimed once, so concurrent deliveries cannot send two receipts.
  • That claim is released on transient failure, so a Paystack retry can complete work that a blip interrupted.
  • A charge that verifies as genuinely unsuccessful keeps its claim and is not retried.

Outbound webhooks

ArayaThrust does not currently send webhooks to customer systems. Integrations that need to react to subscription events must poll or be built against a contract agreed with us.

Email delivery

Transactional mail — verification codes, trial welcome, payment receipts and team notifications — is sent through Amazon SES on an authenticated domain, with DKIM signing and a dedicated MAIL FROM subdomain so SPF alignment is independent of the mailbox provider. Delivery events are published to a notification topic for monitoring.

HMO interconnectivityPlanned

Interconnectivity with NHIA-accredited HMOs is a tier feature described on the Features and Pricing pages. No integration endpoints, credentials or data contracts exist yet, so there is nothing to document. This section will carry the connection model and field mappings once they are built.

Security

Trust model

The guiding rule is that the browser is never trusted with anything that grants entitlement. Payment status comes from Paystack to the server. Plan comes from the verified charge. The account setup token is opaque and carries no claims of its own.

Account handoff tokens

  • Minted only after a charge is verified server-side with Paystack.
  • Cryptographically random and opaque — the token encodes nothing and cannot be inspected or forged into a different plan.
  • Single use. Redemption is conditional, so two simultaneous attempts cannot both succeed; the second is told the token is already used.
  • Time limited, expiring automatically after seven days.
  • Exchanged only server-to-server, over a shared key the browser never sees.

Verification codes

Signup codes are six digits, expire after 10 minutes, and are stored hashed with a server-side pepper rather than in clear text, so possession of the stored record alone does not reveal a usable code. Each record tracks its own attempt count.

Encryption and data protection

  • All API and site traffic is served over TLS.
  • Stored records are encrypted at rest by the managed data stores that hold them.
  • The Paystack secret is held as an encrypted environment value and is never present in the site bundle or in version control.
  • Short-lived records — verification codes, idempotency keys, handoff tokens — carry an expiry and are removed automatically rather than accumulating.

NDPA

ArayaThrust describes itself as aligned to the Nigeria Data Protection Act, including a 90-day retention window for export after a subscription lapses. The compliance position is a matter for the company's published policy rather than for this page.

Reporting a vulnerability

Report suspected vulnerabilities to customercare@arayathrust.com. Please include enough detail to reproduce the issue, and allow time to remediate before any public disclosure.

Operations

Monitoring and diagnostics

Each API route runs as an isolated function with its own log stream, so a failure can be traced to a single route without affecting the others. Email delivery events are published to a notification topic, which is where bounces and complaints surface.

Delivery and retries

Paystack retries any webhook that does not return a 2xx. The webhook is written for that: work is claimed once to prevent duplicates, and the claim is released on transient failure so a retry can finish the job. A failure to send the internal team notification deliberately does not trigger a retry, because that would cost the customer a second receipt.

Backup and recoveryPlanned

Durable subscription records live in managed stores with built-in redundancy, and the short-lived records expire by design rather than being backed up. A documented backup and restore procedure, with stated recovery objectives, is not yet published and will be added here when it is defined.

Troubleshooting

SymptomLikely causeResolution
Checkout shows payment unavailableThe site was built without a Paystack public key.Set the key in the hosting environment and rebuild — it is embedded at build time, so changing it without a rebuild has no effect.
Payment succeeded but no receipt arrivedThe webhook URL is not registered in the Paystack dashboard, or the secret does not match the mode in use.Register the webhook URL in both the test and live dashboards and confirm the secret matches the public key's mode.
Setup link never becomes readyThe webhook has not confirmed the charge.Check webhook delivery in the Paystack dashboard. The emailed link is the fallback and is not affected.
The payment window does not openA content blocker is stripping the embedded Paystack frame.Allow the frame for the checkout page and retry. Checkout reports this rather than appearing to hang.
A verification code is rejectedMore than 10 minutes elapsed.Request a new code rather than retrying the old one.

Last updated 19 October 2026. This documentation tracks the deployed implementation; sections marked Planned describe capability that is not yet available.