Security summary
For the IT teams of businesses connecting their systems to Lekuka through the Marshal Fiscal API. Updated 30 October 2026.
Transport
- HTTPS only. TLS 1.2 and 1.3; older protocols are refused. Plain HTTP is redirected to HTTPS.
- Strict-Transport-Security is sent on every response, for one year, so browsers never fall back to HTTP.
API keys
- Keys belong to one business. Test keys begin mk_test_ and never reach RSL; live keys begin mk_live_.
- A key is shown once, when it is created. We store only its SHA-256 fingerprint, so nobody — including Headway — can read it back.
- A key can be limited to chosen terminals (shops), given an expiry date, and revoked at once. The business sees when and from which address each key was last used.
- Least privilege: each key holds only the scopes it needs — filing (documents:write), reading documents, managing terminals and fiscal days, reading terminals, reading usage. A reporting tool can be given read scopes only; a call outside a key's scopes is refused (403 insufficient_scope).
- A key can be limited to IP addresses or ranges, such as the business's own servers. Used from anywhere else it is refused (403 ip_not_allowed), so a leaked key is of no use outside those addresses.
- Rotation without downtime: rotating a key issues a new one at once and keeps the old one working for an overlap the business chooses (7 days by default, at most 30), after which the old key expires on its own.
Isolation between businesses
- Each key acts only as its own business. Every read and write runs under row-level security in the database, keyed to that business.
- Asking for another business's documents, terminals or devices answers 404 — as if they did not exist.
- Requests are strict: unknown fields are refused rather than ignored, and fields only the server may set cannot be sent.
- Every request that changes something carries an Idempotency-Key, so a retried request is answered from the first one and never acts twice.
Webhook signing
- Every webhook is signed: Marshal-Signature: t=<time>,v1=<HMAC-SHA256 of the time and the body>, with a secret unique to the endpoint.
- Reject anything whose signature does not match or is more than five minutes old. Each event carries an id, so a repeat can be ignored.
- A webhook secret can be rotated at any time from the business's developer settings. For 24 hours after a rotation each delivery is signed with both the new and the old secret, so the receiving system can switch without missing or rejecting deliveries.
Encryption at rest
- API keys are stored only as fingerprints (SHA-256).
- Webhook secrets, fiscal device private keys, accounting-connector credentials and RSL activation keys are encrypted with AES-256 before they are stored.
- Databases are backed up regularly by a separate system.
Logging and audit
- Every API request is logged against its key: method, path, status, duration, address and the error code. Request bodies are not logged.
- Secrets — keys, webhook secrets, device keys — are never written to logs.
- The business can read its own request log in its developer settings.
Retention
- Fiscal documents are kept for as long as Lesotho tax law requires; request logs are deleted after 30 days.
Personal data
- Personal data in documents (a buyer's name or TIN) is used only to file the document with RSL as Lekuka requires, and to show it back to the business that filed it.
- We handle personal data in line with Lesotho's Data Protection Act, 2011.
Reliability
- We aim for 99.5% availability each month and announce planned maintenance in advance; there is no formal service-level agreement yet.
- If RSL is slow or unreachable, documents are kept and filed when it answers again; nothing is lost. Current status: /developers/status.
OWASP API Security Top 10 (2023)
- API1 Broken object level authorisation: every query is limited to the key's own business, and again by row-level security in the database; a key limited to some terminals cannot reach the others; another business's ids answer 404.
- API2 Broken authentication: keys are 40 random characters (about 238 bits), stored only as SHA-256 fingerprints, sent over TLS only, and can expire, be revoked at once or be rotated with an overlap.
- API3 Broken object property level authorisation: requests are decoded strictly (an unknown or server-only field is refused, never ignored), and answers are built field by field, so internal data such as device keys is never returned.
- API4 Unrestricted resource consumption: 600 requests a minute per key with RateLimit headers, 2 MB bodies, at most 500 lines a document, paged lists, and plan allowances that stop live filing when exhausted (402).
- API5 Broken function level authorisation: every operation requires a scope (403 insufficient_scope); opening and closing real fiscal days and enrolling devices need a live key; keys and webhooks are managed only by the business's users who hold its Edit System Configuration permission.
- API6 Unrestricted access to sensitive business flows: filing needs an enrolled device and the taxpayer's own tax table; an Idempotency-Key on every POST and unique invoice numbers stop a retried request filing twice; test keys never reach RSL.
- API7 Server-side request forgery: webhook addresses must be https, and the server refuses to connect to private, loopback or link-local addresses when it delivers, checked at connection time.
- API8 Security misconfiguration: TLS with HSTS, errors in one envelope without internal detail, a narrow CORS policy, and a published security.txt.
- API9 Improper inventory management: one versioned API (/v1) whose published specification is checked against the routes the server serves by an automated test, a dated changelog and a deprecation policy.
- API10 Unsafe consumption of APIs: RSL's gateway is called over verified TLS, and its answers are parsed and checked before anything is recorded; nothing it returns is executed or followed blindly.
- Dependencies are scanned for known vulnerabilities (govulncheck for the server, npm audit for the web app), and findings are tracked and fixed in planned updates.
Testing and reporting
- The API has automated tests, run before changes are released — including a check that the published specification matches what the server serves.
- An independent penetration test is planned before the production service opens.
- Report a suspected vulnerability to security@headway.co.ls (also in /.well-known/security.txt). Please do not access other businesses' data or disrupt the service while testing.
Questions about this page: security@headway.co.ls. Marshal Business Suite is a product of Headway.