{"info":{"title":"Ledgr API","version":"v4","baseUrl":"","description":"Every endpoint Ledgr serves — the same API the Ledgr apps use. There is no reduced \"integration\" surface. Sign in with POST /auth/login for a JWT, or exchange an API key at POST /auth/token. Send X-Company-Id to act within one company of a group. Three limits apply together and the narrowest wins: the tenant's plan, the key's scopes, and the role of the user the key belongs to."},"categories":[{"name":"Authentication","blurb":"Every call carries one Authorization: Bearer header. A person signs in; an integration exchanges an API key. Nothing needs a customer's password.","endpoints":[{"method":"POST","path":"/auth/login","summary":"Exchange email and password for a JWT. A TOTP code and a recovery code go in the same field — they are told apart by shape, six digits against Crockford Base32 ABCDE-FGHJK.","auth":"none","responseExample":{"accessToken":"<jwt>","refreshToken":"<refresh-token>","userId":"05aea44f-e1a0-5fc5-a870-df0697216af5","tenantId":"f80b8d0f-4c0f-58e9-80a4-5915fa569c52","tenantName":"Your Business","email":"you@example.example","role":"owner","firstName":"Thandi","lastName":"Mokoena","mustEnroll2fa":false,"mustChangePassword":false},"body":{"email":"you@example.example","password":"your-password","totpCode":"123456","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","devicePlatform":"android"}},{"method":"POST","path":"/auth/refresh","summary":"Exchange a refresh token for a new access token.","auth":"none","body":{"refreshToken":"<refresh-token>"},"responseExample":{"accessToken":"<never returned>","refreshToken":"<never returned>","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","role":"Accountant","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","entitlements":{"plan":"business","planDisplayName":"Karoo Fresh Holdings Ltd","maxUsers":1,"licenseValidUntil":"2026-09-30","modules":["invoices"],"expired":false,"activeUsers":1,"invoicesThisMonth":9,"invoiceLimit":50,"payrollEmployees":1,"payrollBand":"1 to 10 employees","payrollBandLicensed":"1 to 10 employees","payrollBandMonthly":1.0,"payrollBandExceeded":false,"payrollBandHeadroom":1,"payrollBandSummary":"Consulting services — August 2026","storageUsedBytes":1,"storageUsedGb":1,"storageIncludedGb":1,"storageExtraGb":1,"storageMonthlyUplift":1.0,"storageExceedsLicensed":false,"storageHeadroomGb":1,"storageSummary":"Consulting services — August 2026","whatsAppUsed":1,"whatsAppIncluded":1,"whatsAppExtra":1,"whatsAppMonthlyUplift":1.0,"whatsAppHeadroom":1,"whatsAppSummary":"Consulting services — August 2026","scanUsed":1,"scanIncluded":1,"scanExtra":1,"scanMonthlyUplift":1.0,"scanHeadroom":1,"aiAssist":false,"scanSummary":"Consulting services — August 2026","practiceClients":1,"practicePaidClients":1,"practiceStatus":"sent","practiceStatusName":"Karoo Fresh Holdings Ltd","practicePayoutPercent":0.0,"practiceMonthlyPayout":1.0,"practiceClientsToNextStatus":1,"practiceSummary":"Consulting services — August 2026","planIncludedUsers":1,"companies":1,"maxCompanies":1,"planIncludedCompanies":1,"companiesSummary":"Consulting services — August 2026","addons":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":3,"unitLabel":"Karoo Fresh Holdings Ltd"}],"availableAddons":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":3,"unitLabel":"Karoo Fresh Holdings Ltd"}],"addonsMonthlyTotal":10005.0,"addonUpgradeSuggestion":"The Business plan costs less than your current add-ons.","apiKeysUsed":1,"apiKeysIncluded":1,"apiKeysHeadroom":1,"apiKeysSummary":"Consulting services — August 2026"},"mustEnroll2fa":false,"mustChangePassword":false}},{"method":"POST","path":"/auth/logout","summary":"Revoke the current session. The token stops working on the next request rather than when it expires.","auth":"jwt","responseExample":{"message":"Signed out."}},{"method":"GET","path":"/auth/me","summary":"The signed-in user, their tenant, their roles and the company they are acting in.","auth":"jwt","responseExample":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","role":"Accountant"}},{"method":"POST","path":"/auth/token","summary":"Exchange an API key for a one-hour access token carrying that key's scopes. This is how an integration authenticates; it never needs a user's password.","auth":"api-key","responseExample":{"accessToken":"<jwt>","tokenType":"Bearer","expiresIn":3600,"scope":"invoices:write contacts:read","tenantId":"751f8fc2-155d-50b1-a7e9-eb46ba03ebca","rateLimitPerMinute":120}},{"method":"GET","path":"/oauth/authorize?response_type=code&client_id={clientId}&redirect_uri={uri}&scope={scopes}&state={state}","summary":"OAuth 2: send a person here to connect your app. They sign in on Ledgr's own page, see the scopes you asked for, may untick any, and are returned to your registered redirect with ?code=&state= (or ?error=access_denied). Optional PKCE: code_challenge with code_challenge_method=S256.","auth":"none","responseKind":"html"},{"method":"POST","path":"/oauth/authorize","summary":"The consent page's own form (the person's sign-in and the scopes they ticked). Not called by an app.","auth":"none","responseKind":"redirect"},{"method":"POST","path":"/oauth/token","summary":"OAuth 2 token exchange, form-encoded, with the app's client_id and client_secret (in the form or as HTTP Basic). grant_type=authorization_code with code and redirect_uri (and code_verifier when a challenge was sent) returns an access token and a refresh token; grant_type=refresh_token returns a new access token. The token acts as the person who connected the app, with only the scopes they granted.","auth":"none","responseExample":{"access_token":"<jwt>","token_type":"Bearer","expires_in":3600,"refresh_token":"ledgr_… (keep it secret, with your client secret)","scope":"invoices:read","tenant_id":"751f8fc2-155d-50b1-a7e9-eb46ba03ebca"}},{"method":"GET","path":"/api-scopes","summary":"Every scope an API key can hold, with its label. Unauthenticated, so tooling can render a scope picker without a key.","auth":"none","responseExample":{"scopes":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","module":"invoices","access":"text"}],"notes":"Budget deferred to the next financial year."}},{"method":"POST","path":"/auth/verify-email/resend","summary":"Send the signed-in user another verification email. Five an hour per address.","auth":"jwt","responseExample":{"verified":false,"sent":true}}]},{"name":"Two-factor authentication","blurb":"TOTP with ten single-use recovery codes. Recovery is checked before the encrypted seed is touched, so a rotated secret key is no longer a lockout.","endpoints":[{"method":"POST","path":"/api/users/{id}/2fa/reset?code=123456","summary":"Clear ANOTHER user's 2FA after a lost phone. Needs roles:edit plus an owner or admin role, refuses id == self, revokes the target's sessions, audits at warning and emails them.","auth":"jwt","responseExample":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","hadEnrolledFactor":true,"recoveryCodesRevoked":1,"userNotified":true,"message":"Saved."}}]},{"name":"Tenant, plan & entitlements","blurb":"What this tenant has bought, what it is using, and the guided-setup checklist the dashboard draws.","endpoints":[{"method":"GET","path":"/api/tenant/entitlements","summary":"The plan, its modules, seat and storage allowances, live usage against them, and the licence's expiry. The client calls this at app start and from its nav guard.","auth":"jwt","responseExample":{"plan":"business","planDisplayName":"Karoo Fresh Holdings Ltd","maxUsers":1,"licenseValidUntil":"2026-09-30","modules":["invoices"],"expired":false,"activeUsers":1,"invoicesThisMonth":9,"invoiceLimit":50,"payrollEmployees":1,"payrollBand":"1 to 10 employees","payrollBandLicensed":"1 to 10 employees","payrollBandMonthly":1.0,"payrollBandExceeded":false,"payrollBandHeadroom":1,"payrollBandSummary":"Consulting services — August 2026","storageUsedBytes":1,"storageUsedGb":1,"storageIncludedGb":1,"storageExtraGb":1,"storageMonthlyUplift":1.0,"storageExceedsLicensed":false,"storageHeadroomGb":1,"storageSummary":"Consulting services — August 2026","whatsAppUsed":1,"whatsAppIncluded":1,"whatsAppExtra":1,"whatsAppMonthlyUplift":1.0,"whatsAppHeadroom":1,"whatsAppSummary":"Consulting services — August 2026","scanUsed":1,"scanIncluded":1,"scanExtra":1,"scanMonthlyUplift":1.0,"scanHeadroom":1,"aiAssist":false,"scanSummary":"Consulting services — August 2026","practiceClients":1,"practicePaidClients":1,"practiceStatus":"sent","practiceStatusName":"Karoo Fresh Holdings Ltd","practicePayoutPercent":0.0,"practiceMonthlyPayout":1.0,"practiceClientsToNextStatus":1,"practiceSummary":"Consulting services — August 2026","planIncludedUsers":1,"companies":1,"maxCompanies":1,"planIncludedCompanies":1,"companiesSummary":"Consulting services — August 2026","addons":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":3,"unitLabel":"Karoo Fresh Holdings Ltd"}],"availableAddons":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":3,"unitLabel":"Karoo Fresh Holdings Ltd"}],"addonsMonthlyTotal":10005.0,"addonUpgradeSuggestion":"The Business plan costs less than your current add-ons.","apiKeysUsed":1,"apiKeysIncluded":1,"apiKeysHeadroom":1,"apiKeysSummary":"Consulting services — August 2026"}},{"method":"GET","path":"/api/tenant-settings","summary":"The Settings screen's stored blob — company details, fiscal year, VAT profile, regional and notification preferences.","auth":"jwt","responseExample":{"taxVat":{"isVatRegistered":true,"vatRegistrationDate":"2026-09-01","vatPeriod":"2026-09","standardVatRate":15.0,"drcEnabled":false,"provisionalTaxPayer":true,"sarsIsvConnected":false,"sarsTaxRefNumber":"INV-0001","incomeTaxRate":15.0},"branding":{"brandColorHex":"#0D47A1"},"localisation":{"currency":"ZAR","dateFormat":"day-month-year","numberFormat":"space-point"},"integrations":{"key":true},"notifications":{"key":true},"dataPrefs":{"autoBackupEnabled":true,"autoBackupFrequency":"monthly","retentionMonths":84}}},{"method":"GET","path":"/api/tenant-settings/presentation","summary":"How the tenant chose to have Ledgr drawn — brand colour, date format and number format. Any member of the tenant may read it; the rest of the settings is Owner and Admin only.","auth":"jwt","responseExample":{"brandColorHex":"#0D47A1","dateFormat":"day-month-year","numberFormat":"space-comma"}},{"method":"PUT","path":"/api/tenant-settings","summary":"Save settings, section by section: each section you send replaces that section whole, and a section you leave out keeps its stored value. A body naming no known section is refused rather than answered 200. Every save writes one audit-log row listing each field it changed, from and to. Answers with the merged result.","auth":"jwt","body":{"taxVat":{"isVatRegistered":true,"vatRegistrationDate":"2019-04-01","standardVatRate":15.0,"drcEnabled":false,"provisionalTaxPayer":true,"sarsTaxRefNumber":"9012345678"},"branding":{"brandColorHex":"#0D47A1"},"localisation":{"currency":"ZAR","dateFormat":"day-month-year","numberFormat":"space-point"},"integrations":{"whatsapp":true},"notifications":{"email-overdue-invoice":true,"wa-overdue-followup":false},"dataPrefs":{"autoBackupEnabled":false,"autoBackupFrequency":"Daily","retentionMonths":84}},"responseExample":{"taxVat":{"isVatRegistered":true,"vatRegistrationDate":"2026-09-01","vatPeriod":"2026-09","standardVatRate":15.0,"drcEnabled":false,"provisionalTaxPayer":true,"sarsIsvConnected":false,"sarsTaxRefNumber":"INV-0001","incomeTaxRate":15.0},"branding":{"brandColorHex":"#0D47A1"},"localisation":{"currency":"ZAR","dateFormat":"day-month-year","numberFormat":"space-point"},"integrations":{"key":true},"notifications":{"key":true},"dataPrefs":{"autoBackupEnabled":true,"autoBackupFrequency":"monthly","retentionMonths":84}}},{"method":"GET","path":"/api/approvals/waiting","summary":"What the signed-in person may decide: submitted expense claims, pending leave, purchase requisitions awaiting them and job cards awaiting sign-off. Each kind appears only with its approve permission and its module; lists are capped per kind, newest first, and the counts are the true totals.","auth":"jwt","responseExample":{"items":[{"kind":"claim","id":"3f6b2a10-5c1e-4d7a-9b0e-2a8c4d6e8f01","title":"R 517.50 · Fuel — Buyer User","amount":517.5,"currency":"ZAR","raisedBy":"Buyer User","raisedAt":"2026-10-10T07:15:00Z"}],"counts":{"claims":1,"leave":0,"requisitions":0,"jobSignOffs":0},"total":1,"perKindLimit":50}},{"method":"POST","path":"/api/data/export","summary":"A ZIP of CSVs — every table this tenant owns — and every file the tenant uploaded, byte for byte under files/, listed in files/manifest.csv. The export is what the retention notices lead with, because the Tax Administration Act asks a business to keep records for five years.","auth":"jwt","responseKind":"binary"},{"method":"GET","path":"/api/data/backups","summary":"The off-site backups Ledgr is holding for this tenant, plus what the schedule is doing. `nextDueOn` is null when automatic backups are switched off.","auth":"jwt","responseExample":{"backups":[{"id":"72f394e2-8dc2-4722-9fc1-591469e089e6","takenOn":"2026-09-03","sizeBytes":13367,"fileCount":10,"kind":"auto","status":"success","error":null,"frequency":"daily"}],"lastBackupAt":"2026-09-03","totalSizeBytes":13367,"enabled":true,"frequency":"daily","retentionMonths":84,"nextDueOn":"2026-09-04"}},{"method":"POST","path":"/api/data/backups","summary":"Back up now. Never deduped — pressing it twice takes two backups, unlike the scheduled run, which is idempotent per period.","auth":"jwt","responseExample":{"ok":true,"backup":{"id":"72f394e2-8dc2-4722-9fc1-591469e089e6","takenOn":"2026-09-03","sizeBytes":13367,"fileCount":10,"kind":"manual","status":"success","error":null,"frequency":null},"message":null,"prunedCount":0}},{"method":"GET","path":"/api/data/backups/{id}/download","summary":"A short-lived signed URL for one backup. JSON rather than a 302: a redirect would carry the Ledgr bearer token to the storage host. Another tenant's id answers 404, never 403.","auth":"jwt","responseExample":{"url":"https://storage.googleapis.com/ledgr-uploads/tenants/087df7f1/backups/23ed50ed.zip?X-Goog-Signature=abc","expiresInSeconds":300}},{"method":"POST","path":"/api/data/backups/{id}/restore/preview","summary":"What restoring this backup WOULD do. Writes nothing. Its own endpoint rather than a flag on the write, so the safe call cannot become the dangerous one by a typo in a query string.","auth":"jwt","responseExample":{"applied":false,"summary":"3 records can be put back, 1 cannot.","restorable":3,"blocked":1,"unchanged":41,"byTable":{"invoices":1,"invoice_lines":2},"decisions":[{"table":"invoices","id":"6a3f1c22-2f0f-4bd1-8f4f-1b2a5d3e9c77","label":"INV-2026-014","date":"2026-08-14","verdict":"RESTORE","reason":"Deleted since the backup — will be restored."}],"decisionsTruncated":false,"journalsReposted":0,"notRestorable":null}},{"method":"POST","path":"/api/data/backups/{id}/restore","summary":"Put back records the books no longer hold. Adds only — never overwrites a live row and never deletes anything. A row inside a closed accounting period is refused with the period named; the ledger is re-posted by the posting engine rather than copied out of the backup.","auth":"jwt","responseExample":{"applied":false,"summary":"3 records can be put back, 1 cannot.","restorable":3,"blocked":1,"unchanged":41,"byTable":{"invoices":1,"invoice_lines":2},"decisions":[],"decisionsTruncated":false,"journalsReposted":2,"notRestorable":null}}]},{"name":"Users, roles & security","blurb":"Eight system roles, six actions per module, and a POPIA-retained audit log. A role decides what a person may do; the plan decides what the tenant bought.","endpoints":[{"method":"GET","path":"/api/users","summary":"Tenant users with their roles, 2FA state, session count and company access.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"lastLoginAt":"2026-09-01T09:15:00Z","twoFactorEnabled":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/users/invite","summary":"Invite a colleague, choosing their role and which companies they may reach.","auth":"jwt","responseExample":{"user":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"lastLoginAt":"2026-09-01T09:15:00Z","twoFactorEnabled":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"tempPassword":"<never returned>","emailed":true},"body":{"email":"accounts@karoofresh.example","firstName":"Thandi","lastName":"Mokoena","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tempPassword":"Welcome-2026!","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]}},{"method":"PUT","path":"/api/users/{id}","summary":"Change a user's name, role, active flag or company access.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"lastLoginAt":"2026-09-01T09:15:00Z","twoFactorEnabled":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","firstName":"Thandi","lastName":"Mokoena","isActive":true}},{"method":"DELETE","path":"/api/users/{id}","summary":"Deactivate a user and revoke their sessions.","auth":"jwt","responseKind":"none"},{"method":"POST","path":"/api/users/{id}/revoke-sessions","summary":"Sign a user out everywhere without deactivating them.","auth":"jwt","responseExample":{"revoked":1}},{"method":"POST","path":"/api/users/{id}/transfer-ownership","summary":"Hand the tenant's single owner seat to another user. Gated harder than ordinary user management on purpose: `roles:edit` alone is not enough, because that permission is grantable to a custom role and giving away the god-mode seat is a different order of act from renaming one — only the current owner/admin may call it, and never on themselves. One transaction demotes the outgoing owner and promotes the target together, so the account is never briefly left with none or with two.","auth":"jwt","responseExample":{"previousOwner":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"lastLoginAt":"2026-09-01T09:15:00Z","twoFactorEnabled":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"newOwner":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","role":"Accountant","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"lastLoginAt":"2026-09-01T09:15:00Z","twoFactorEnabled":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"message":"Saved."},"body":{"roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},{"method":"GET","path":"/api/roles","summary":"System and custom roles. The eight that ship are Owner, Admin, Accountant, Sales, Viewer, Payroll Manager, Tax Practitioner and External Auditor, plus Buyer, Production Planner and Fleet Controller where the plan carries them.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","isSystem":false,"permissions":[{"resource":"invoices","action":"created"}],"userCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/roles","summary":"Create a custom role.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","isSystem":false,"permissions":[{"resource":"invoices","action":"created"}],"userCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Branch manager","description":"Sells and banks, cannot see payroll","permissions":[{"resource":"invoices","action":"view"}]}},{"method":"PUT","path":"/api/roles/{id}","summary":"Rename or re-describe a role.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","isSystem":false,"permissions":[{"resource":"invoices","action":"created"}],"userCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Branch manager","description":"Consulting services — August 2026"}},{"method":"DELETE","path":"/api/roles/{id}","summary":"Delete a custom role. A system role cannot be deleted.","auth":"jwt","responseKind":"none"},{"method":"GET","path":"/api/roles/{id}/permissions","summary":"The full permission matrix for one role — every module against view, create, edit, delete, approve and export.","auth":"jwt","responseExample":[{"resource":"invoices","action":"created"}]},{"method":"PUT","path":"/api/roles/{id}/permissions","summary":"Replace a role's permission matrix.","auth":"jwt","responseKind":"none","body":{"permissions":[{"resource":"invoices","action":"view"}]}},{"method":"GET","path":"/api/roles/my-permissions","summary":"What the calling user may do, resolved. The client's nav guard reads this rather than inferring it from a role name.","auth":"jwt","responseExample":{"roleName":"Karoo Fresh Holdings Ltd","legacyRole":"Accountant","superuser":false,"permissions":[{"resource":"invoices","action":"created"}]}},{"method":"GET","path":"/api/audit-log?page=1&severity=warning&since=2026-03-01&action=sars.submit&excludeSignIns=true","summary":"Audit events with severity filtering; excludeSignIns=true leaves out sign-ins and sign-outs. Retained seven years for POPIA.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorEmail":"accounts@karoofresh.example","action":"created","resourceType":"standard","resourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","severity":"text","payload":"text","ipAddress":"12 Long Street, Cape Town, 8001","userAgent":"text","createdAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50}},{"method":"GET","path":"/api/security-policy","summary":"Session timeout, password policy, lockout rules, whether admins must hold 2FA, and the retention period.","auth":"jwt","responseExample":{"sessionTimeoutMins":60,"passwordMinLength":8,"passwordRequireUpper":true,"passwordRequireDigit":true,"passwordRequireSpecial":false,"lockoutMaxAttempts":5,"lockoutWindowMins":15,"require2faForAdmins":false,"require2faForEveryone":false,"retentionDays":2555,"retentionFloorDays":2555,"retentionNote":null,"maxDevicesPerUser":3}},{"method":"PUT","path":"/api/security-policy","summary":"Replace the security policy — send every field, because one left out goes back to its default. The example body IS those defaults, so sending it as it stands changes nothing that would lock anyone out: change only the fields you mean to. Requiring 2FA for admins (require2faForAdmins: true) is enforced server-side, not advised to the client — every owner and admin without 2FA is limited to enrolling at their next sign-in, so enrol first.","auth":"jwt","body":{"sessionTimeoutMins":60,"passwordMinLength":8,"passwordRequireUpper":true,"passwordRequireDigit":true,"passwordRequireSpecial":false,"lockoutMaxAttempts":5,"lockoutWindowMins":15,"require2faForAdmins":false,"require2faForEveryone":false,"retentionDays":2555,"retentionFloorDays":2555,"retentionNote":null,"maxDevicesPerUser":3},"responseExample":{"sessionTimeoutMins":60,"passwordMinLength":8,"passwordRequireUpper":true,"passwordRequireDigit":true,"passwordRequireSpecial":false,"lockoutMaxAttempts":5,"lockoutWindowMins":15,"require2faForAdmins":false,"require2faForEveryone":false,"retentionDays":2555,"retentionFloorDays":2555,"retentionNote":null,"maxDevicesPerUser":3}}]},{"name":"API keys","blurb":"A key is a ceiling, never a grant: it can do nothing its owning user cannot. Created here, exchanged for a token at POST /auth/token.","endpoints":[{"method":"GET","path":"/api/api-keys","summary":"Keys for this tenant — name, scopes, bound contact, last use. The secret is never returned again.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","scopes":["text"],"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lastUsedAt":"2026-09-01T09:15:00Z","expiresAt":"2026-09-01T09:15:00Z","revokedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","description":"Consulting services — August 2026","rateLimitPerMin":1,"requestCount":3}]},{"method":"GET","path":"/api/api-keys/readiness/{integration}","summary":"Whether this business holds a live, unexpired key whose scopes permit every call an API-key integration makes (integration: ruva). Read off the key table and the key gate's own scope rules.","auth":"jwt","responseExample":{"integration":"ruva","ready":false,"keyName":"Ruva POS","keyLastUsedAt":"2026-09-01T09:15:00Z","requiredScopes":["multi-company:read","reports:write"]}},{"method":"POST","path":"/api/api-keys","summary":"Generate a key. The plaintext is shown ONCE in this response. Bind it to a contact if it will post billable events for one. Give actsAsRoleId to make a key the business owns: it acts with that role, not as you, and keeps working if you leave.","auth":"jwt","responseExample":{"key":{"id":"1da01faf-df19-565a-b682-5fc3d4eafa05","tenantId":"a911913b-e9a4-58ad-8a64-74ca2f3990e3","userId":"5ff68b17-8b62-5ca4-8994-991e33df27cd","name":"Warehouse sync","keyPrefix":"ledgr_live_9f2c","scopes":["inventory:read","inventory:write"],"createdAt":"2026-09-01T09:00:00Z"},"plaintextKey":"ledgr_live_… (shown once, never again)"},"body":{"name":"Warehouse sync","scopes":["inventory:read","inventory:write"],"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","expiresInDays":30,"description":"Consulting services — August 2026","rateLimitPerMin":1,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actsAsRoleId":"6b0e2d4a-9c1f-4e7a-8d35-1f2a3b4c5d6e","workCentreIds":[]}},{"method":"GET","path":"/api/oauth/apps","summary":"The apps this business has registered to connect to other Ledgr businesses through OAuth.","auth":"jwt","responseExample":[{"id":"0c5a7e2b-3d4f-4a61-9b8c-2e1f0a9d7c35","name":"Ledger Sync","clientId":"lc_app_8Jx2Qm4Vt7Ry1Lp0","redirectUris":["https://app.example.com/ledgr/callback"],"createdAt":"2026-10-11T09:00:00Z"}]},{"method":"POST","path":"/api/oauth/apps","summary":"Register an app. The client secret is shown ONCE in this response. Redirects must be https (http to localhost for testing) and are matched exactly.","auth":"jwt","responseExample":{"app":{"id":"0c5a7e2b-3d4f-4a61-9b8c-2e1f0a9d7c35","name":"Ledger Sync","clientId":"lc_app_8Jx2Qm4Vt7Ry1Lp0","redirectUris":["https://app.example.com/ledgr/callback"],"createdAt":"2026-10-11T09:00:00Z"},"clientSecret":"lcs_… (shown once, never again)"},"body":{"name":"Ledger Sync","redirectUris":["https://app.example.com/ledgr/callback"]}},{"method":"DELETE","path":"/api/oauth/apps/{id}","summary":"Withdraw an app: no new connections, and no connection already made can refresh its token. Access tokens already issued lapse within the hour.","auth":"jwt","responseKind":"none"},{"method":"DELETE","path":"/api/api-keys/{id}","summary":"Revoke a key. It stops working on the next request, not when its last token expires.","auth":"jwt","responseKind":"none"},{"method":"GET","path":"/api/api-keys/usage?days=30","summary":"Per-key call counts and throttling. Metering is per replica, so a tenant's effective limit is N times the published one — see the KDoc on ApiKeyMetering.","auth":"jwt","responseExample":[{"apiKeyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","scopes":["text"],"rateLimitPerMinute":1,"totalRequests":1,"lastUsedAt":"2026-09-01T09:15:00Z","days":[{"date":"2026-09-01","requests":1,"clientErrors":0,"serverErrors":0,"throttled":1}]}]}]},{"name":"Webhooks","blurb":"Ledgr posts an event to your address when a stop's status changes, a proof of delivery is recorded, a trip is dispatched or completed, or an invoice is paid. Every delivery is signed (webhook-id, webhook-timestamp, webhook-signature: v1,<base64 HMAC-SHA256 of id.timestamp.body>), retried with backoff for most of a day, and logged. A subscription reaches only the data its events' API scopes allow.","endpoints":[{"method":"GET","path":"/api/webhooks/events","summary":"The events a subscription may ask for, each with the API scope its data needs.","auth":"jwt","responseExample":[{"type":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","scope":"text"}]},{"method":"GET","path":"/api/webhooks","summary":"This tenant's webhooks with the outcome of each one's most recent delivery. The signing secret is never returned again.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","url":"https://app.ledgrsa.com/pay/3f1a7c92","events":["text"],"active":true,"secretHint":"text","apiKeyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lastDeliveryStatus":"delivered","lastDeliveryAt":"2026-09-01T09:15:00Z","lastStatusCode":1,"lastError":"text","pendingCount":3,"createdAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/webhooks","summary":"Add a webhook. The signing secret is returned ONCE, in this response. Refused for a private or loopback address, an http:// address, or an event the caller's role or API key cannot read.","auth":"jwt","body":{"name":"Online store","url":"https://hooks.example/ledgr","events":["logistics.stop.status_changed","logistics.proof.recorded"],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"subscription":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","url":"https://app.ledgrsa.com/pay/3f1a7c92","events":["text"],"active":true,"secretHint":"text","apiKeyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lastDeliveryStatus":"delivered","lastDeliveryAt":"2026-09-01T09:15:00Z","lastStatusCode":1,"lastError":"text","pendingCount":3,"createdAt":"2026-09-01T09:15:00Z"},"signingSecret":"<never returned>"}},{"method":"PUT","path":"/api/webhooks/{id}","summary":"Change a webhook's name, address or events, or switch it off and on. Only the fields sent change. Events waiting while it was off are sent when it is switched back on.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","url":"https://app.ledgrsa.com/pay/3f1a7c92","events":["text"],"active":true,"secretHint":"text","apiKeyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lastDeliveryStatus":"delivered","lastDeliveryAt":"2026-09-01T09:15:00Z","lastStatusCode":1,"lastError":"text","pendingCount":3,"createdAt":"2026-09-01T09:15:00Z"},"body":{"name":"Online store","url":"https://hooks.example/ledgr","events":["logistics.stop.status_changed","logistics.proof.recorded"],"active":true}},{"method":"DELETE","path":"/api/webhooks/{id}","summary":"Delete a webhook. Anything still waiting to be sent to it is marked failed.","auth":"jwt","responseExample":{"status":"deleted"}},{"method":"GET","path":"/api/webhooks/{id}/deliveries","summary":"The most recent deliveries to one webhook, newest first — status, attempts, the receiver's last HTTP status and why an attempt failed. Takes limit (1-200, default 50).","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","eventId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","eventType":"standard","status":"pending","attempts":1,"lastStatusCode":1,"lastError":"text","nextAttemptAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/webhooks/{id}/deliveries/{deliveryId}/redeliver","summary":"Send a finished delivery again — the same event, under the same event id, so a receiver that dedupes by id takes it as the one it missed. Retried on the ordinary schedule if it fails again. 409 while the webhook is switched off or the delivery is still being tried.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","eventId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","eventType":"standard","status":"pending","attempts":1,"lastStatusCode":1,"lastError":"text","nextAttemptAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}},{"method":"POST","path":"/api/webhooks/{id}/test","summary":"Send one signed webhook.test event now and report what the receiver answered. Not retried.","auth":"jwt","responseExample":{"delivered":true,"statusCode":1,"error":"text","eventId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}]},{"name":"Files & attachments","blurb":"Uploaded bytes live in Cloud Storage, never in Postgres. Generated documents — invoices, payslips, returns — are computed on demand and never stored.","endpoints":[{"method":"GET","path":"/api/files/{id}?variant=thumb","summary":"Returns a short-lived signed URL as JSON, deliberately NOT a 302: a redirect would carry your Ledgr token into Google's request logs, because HTTP clients re-send headers across a redirect. A miss answers 404, not 403, so an id cannot be probed for.","auth":"jwt","responseExample":{"url":"https://storage.googleapis.com/…?X-Goog-Signature=…","expiresInSeconds":900,"contentType":"image/jpeg","sizeBytes":184320}}]},{"name":"Search, insights & deadlines","blurb":"The three things the dashboard chrome reads. Each gates itself on the tenant's plan and the caller's role rather than trusting the nav to hide it.","endpoints":[{"method":"GET","path":"/api/tax-deadlines","summary":"The SARS calendar for this tenant, gated by its VAT category, employer registration and fiscal year end — so a non-employer is not chased for an EMP201. A period past its date stays listed, first and marked overdue (with daysLate and overdueCount), until its return is recorded as filed. For an employee ended as deceased it lists the certificate owed to the executor of the estate (type \"IRP5 to the executor\"), due 14 days after the death.","auth":"jwt","responseExample":[{"type":"standard","period":"2026-09","dueDate":"2026-09-01"}]}]},{"name":"Push notifications","blurb":"Where a server-raised notification is delivered. Every route here is scoped to the caller's own tenant and user — there is no id parameter — so registering, listing and revoking act only on the device in the caller's hand. The four topics and their switches are the same ones the app shows in Settings; a deployment with no Firebase project answers serverConfigured=false and every send is a no-op rather than a silent failure.","endpoints":[{"method":"GET","path":"/api/alert-rules","summary":"The signed-in person's own alert rules (market-platform T-P2.10): each a kind from a closed vocabulary with that person's numbers. Evaluated daily by the alert-rules job; a rule fires once per (rule, record, crossing) into its owner's inbox and push.","auth":"jwt","responseExample":[{"id":"5d1e6a2b-8c4f-4b7e-9a31-0f2c7d9e1b44","kind":"invoice-overdue","amount":50000.0,"days":30,"description":"An invoice over R50000 overdue 30 days","createdAt":"2026-10-11T08:00:00Z"}]},{"method":"POST","path":"/api/alert-rules","summary":"Create an alert rule for the signed-in person. kind is one of invoice-overdue (amount, days), bank-balance-under (amount), bill-due-soon (days), stock-under-reorder, deal-untouched (days). Refused 403 when the caller's role cannot open the records the kind watches; at most 25 rules per person.","auth":"jwt","body":{"kind":"invoice-overdue","amount":50000.0,"days":30},"responseExample":{"id":"5d1e6a2b-8c4f-4b7e-9a31-0f2c7d9e1b44","kind":"invoice-overdue","amount":50000.0,"days":30,"description":"An invoice over R50000 overdue 30 days","createdAt":"2026-10-11T08:00:00Z"}},{"method":"DELETE","path":"/api/alert-rules/{id}","summary":"Delete one of the signed-in person's own alert rules. 404 for anybody else's.","auth":"jwt","responseKind":"none"},{"method":"GET","path":"/api/inbox?limit=30&before=2026-10-11T08:30:00Z","summary":"The signed-in person's inbox (market-platform T-P2.9): every notification sent to them — each push topic, approval request, 'assigned to you' and emailed digest — newest first, with the unread count for the bell. Never anybody else's. Kept 90 days. ?limit= (default 30, max 100) and ?before=<an item's createdAt> page back.","auth":"jwt","responseExample":{"items":[{"id":"8b0c2f1e-5a7d-4c39-9f6e-2d4a1b3c5e70","topic":"push-payment-received","title":"Payment received","body":"R 4 600.00 received from Umlazi Bakery for INV-0042.","route":"invoices","read":false,"createdAt":"2026-10-11T07:42:10Z"}],"unread":1}},{"method":"GET","path":"/api/inbox/unread","summary":"How many of the signed-in person's inbox items are unread — the bell's badge.","auth":"jwt","responseExample":{"unread":3}},{"method":"POST","path":"/api/inbox/read","summary":"Mark the named items read — or, with no ids, everything — for the signed-in person only. Read here is read on every device.","auth":"jwt","body":{"ids":["8b0c2f1e-5a7d-4c39-9f6e-2d4a1b3c5e70"]},"responseExample":{"marked":1,"unread":2}}]},{"name":"Contacts","blurb":"Accounts receivable and the address book. Every figure here describes money already invoiced — the pre-invoice half is Sales CRM.","endpoints":[{"method":"GET","path":"/api/contacts?type=CUSTOMER&page=1&search=cape","summary":"List contacts. Filter by ?type=CUSTOMER|SUPPLIER|EMPLOYEE|TAX_PRACTITIONER.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":1.0,"creditUsed":1.0,"addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"South Africa","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":1,"notes":"Budget deferred to the next financial year.","isActive":true,"tags":["text"],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts","summary":"Create a contact.","auth":"jwt","responseExample":{"id":"18169b6d-4ef1-5921-a7b7-5ae5be060f91","contactType":"customer","name":"Acme Pty Ltd","creditLimit":50000.0,"creditUsed":0.0,"createdAt":"2026-09-01T09:00:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"billing@acme.example","phone":"+27210000000","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":50000.0,"groupCompanyId":null,"addressLine1":"123 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"ZA","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":30,"notes":"Budget deferred to the next financial year.","tags":["wholesale"],"remindersPaused":false,"connectedPerson":false,"alsoCustomer":false,"alsoSupplier":false,"documentLanguage":"af","customFields":{"f1a2b3c4":"Thandi Mokoena"}},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/history-archive","summary":"A contact's settled documents and payments from before the switch, for reference. In no balance, ageing, VAT return or report.","auth":"jwt","responseExample":{"documents":[{"kind":"invoice","number":"INV-1042","issueDate":"2025-11-03","paidDate":"2025-12-01","total":1150.0,"vat":150.0,"amountPaid":1150.0,"currency":"ZAR"}],"payments":[{"date":"2025-12-01","reference":"RCPT-9","amount":1150.0,"allocations":[{"documentNumber":"INV-1042","amount":1150.0}]}]},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}","summary":"One contact with its full detail grid and credit position.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":1.0,"creditUsed":1.0,"addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"South Africa","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":1,"notes":"Budget deferred to the next financial year.","isActive":true,"tags":["text"],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/sites","summary":"A customer's delivery sites — one per branch or depot they take delivery at — the default first.","auth":"jwt","responseExample":[],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/sites","summary":"Add a delivery site. Refused without a name, or without a street address, town or postal code a driver can find. The first site, or one sent as the default, becomes the default.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","addressLine1":"12 Long Street","addressLine2":"Woodstock","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","province":"Western Cape","latitude":1.0,"longitude":1.0,"locationSource":"referral","isDefault":false},"body":{"label":"Durban branch","addressLine1":"12 Point Road","addressLine2":null,"suburb":"Point","city":"Durban","postalCode":"4001","province":"KwaZulu-Natal","isDefault":false},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PUT","path":"/api/contacts/{id}/sites/{siteId}","summary":"Edit a delivery site. Documents that shipped there keep their own snapshot of the address.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","addressLine1":"12 Long Street","addressLine2":"Woodstock","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","province":"Western Cape","latitude":1.0,"longitude":1.0,"locationSource":"referral","isDefault":false},"body":{"label":"Durban branch","addressLine1":"40 Mahatma Gandhi Road","addressLine2":null,"suburb":"Point","city":"Durban","postalCode":"4001","province":"KwaZulu-Natal","isDefault":true},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"DELETE","path":"/api/contacts/{id}/sites/{siteId}","summary":"Remove a delivery site. Documents and stops that used it keep their own copy of the address.","auth":"jwt","responseKind":"none","module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PUT","path":"/api/contacts/{id}","summary":"Update a contact in place.","auth":"jwt","body":{"name":"Acme Pty Ltd","email":"newbilling@acme.example","creditLimit":75000.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":1.0,"creditUsed":1.0,"addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"South Africa","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":1,"notes":"Budget deferred to the next financial year.","isActive":true,"tags":["text"],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PATCH","path":"/api/contacts/{id}","summary":"Apply an edit made against a copy of the contact, merged with anything changed since: fields nobody else changed are written, a field changed elsewhere to a different value answers 409 with both values and writes nothing, and a replayed edit id is answered as done.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":1.0,"creditUsed":1.0,"addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"South Africa","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":1,"notes":"Budget deferred to the next financial year.","isActive":true,"tags":["text"],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"editId":"9b2e4c61-7a3d-4f58-8e0c-1d6a5b3c2f47","base":{"email":"accounts@capeunion.example"},"changes":{"email":"finance@capeunion.example"},"baseUpdatedAt":"2026-09-01T09:15:00Z","conflicts":[]},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"DELETE","path":"/api/contacts/{id}","summary":"Soft-delete a contact.","auth":"jwt","responseKind":"none","module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PATCH","path":"/api/contacts/{id}/tags","summary":"Set the badges — VIP, At Risk, NPO, B-BBEE level.","auth":"jwt","body":{"tags":["VIP","BBBEE-2"]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactType":"customer","name":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","mobile":"+27 82 555 0143","vatNumber":"4123456789","registrationNo":"2021/123456/07","creditLimit":1.0,"creditUsed":1.0,"addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","province":"Western Cape","postalCode":"CT-001","country":"South Africa","postalAddressLine1":"12 Long Street","postalAddressLine2":"Woodstock","postalCity":"Cape Town","postalProvince":"Western Cape","postalPostalCode":"CT-001","postalCountry":"South Africa","currency":"ZAR","paymentTerms":1,"notes":"Budget deferred to the next financial year.","isActive":true,"tags":["text"],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/{id}/merge","summary":"Merge this contact into the survivor. Re-points every linked record rather than copying it, archives this contact, and records exactly what moved so the merge can be undone.","auth":"jwt","responseExample":{"ok":true,"survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mergeId":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","moved":{"invoices":3,"contact_people":1},"contactId":"5b9c2e71-8a44-4d13-a0f6-3e7d1c9b2a55"},"body":{"survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/merge","summary":"Merge several duplicates into one survivor in one request. Each is recorded as its own merge, so each can be undone on its own; one contact that cannot be merged refuses the lot.","auth":"jwt","responseExample":{"survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","merges":[{"ok":true,"survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mergeId":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","moved":{"invoices":2},"contactId":"5b9c2e71-8a44-4d13-a0f6-3e7d1c9b2a55"}]},"body":{"survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/merges/{mergeId}/undo","summary":"Undo a merge: the records it moved go back to the contact it archived, which is restored. Anything the survivor gained after the merge stays with the survivor.","auth":"jwt","responseExample":{"mergeId":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","contactId":"5b9c2e71-8a44-4d13-a0f6-3e7d1c9b2a55","survivorId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movedBack":{"invoices":2},"message":"Dup Co is restored with 2 records moved back."},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/{id}/restore","summary":"Bring an archived contact back. A contact archived by a merge is refused, naming the merge to undo instead.","auth":"jwt","responseExample":{"id":"5b9c2e71-8a44-4d13-a0f6-3e7d1c9b2a55","tenantId":"c4a17e90-2d35-4b8f-9e61-7a0d3f5b2c18","contactType":"customer","name":"Acme Trading","createdAt":"2026-09-01T08:00:00Z","updatedAt":"2026-09-16T10:12:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/bills","summary":"The supplier half of an account: this contact's bills, newest first, and what is still owed on them. Needs expenses:view as well as contacts:view; the balance alone is /api/contacts/{id}/balance.","auth":"jwt","responseExample":{"bills":[{"id":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","billNumber":"TKM-7741290","issueDate":"2026-08-06","dueDate":"2026-09-05","amount":2868.57,"vatAmount":430.29,"total":3298.86,"status":"due"}],"owed":3298.86,"openCount":1,"total":1,"limit":100},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/balance?asOf=2026-11-10","summary":"What a contact owes and is owed, without the documents behind it: the receivable ageing, what is owed on open bills, and the statement's open items as the statement PDF prints them. On contacts:view alone; the invoice and bill lists need invoices:view and expenses:view.","auth":"jwt","responseExample":{"ageing":{"current":11500.0,"days30":0.0,"days60":0.0,"days90":0.0,"overdue":0.0,"days1to30":0.0,"notYetDue":11500.0},"owed":3298.86,"openBillCount":1,"statementItems":[{"id":"","number":"INV-0042","documentType":"invoice","issueDate":"2026-11-01","dueDate":"2026-12-01","total":11500.0,"amountDue":11500.0,"status":"open"}]},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/price-list","summary":"The customer's default price list, with every price on it — what their invoices, quotes, job cards and portal orders are priced from. No list is a null priceList.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceList":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","prices":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","unitPrice":2900.0}]}},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"PUT","path":"/api/contacts/{id}/price-list","summary":"Choose the customer's default price list; a null priceListId clears it.","auth":"jwt","body":{"priceListId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceList":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","prices":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","unitPrice":2900.0}]}},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/people","summary":"The people at a contact — accounts, buyers, directors — each with their own address.","auth":"jwt","responseExample":[{"id":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","role":"accounts","email":"accounts@acme.example","phone":"+27 11 555 0101","includeInStatements":false,"createdAt":"2026-09-16T10:00:00Z","updatedAt":"2026-09-16T10:00:00Z"}],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/people","summary":"Add a person to a contact. A person marked to receive statements must have an email address.","auth":"jwt","body":{"name":"Thandi Mokoena","role":"accounts","email":"accounts@acme.example","phone":"+27 11 555 0101","includeInStatements":true},"responseExample":{"id":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","role":"accounts","email":"accounts@acme.example","phone":"+27 11 555 0101","includeInStatements":false,"createdAt":"2026-09-16T10:00:00Z","updatedAt":"2026-09-16T10:00:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PUT","path":"/api/contacts/{id}/people/{personId}","summary":"Replace a person's details.","auth":"jwt","body":{"name":"Thandi Mokoena","role":"accounts","email":"payables@acme.example","phone":"+27 11 555 0101","includeInStatements":true},"responseExample":{"id":"8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","role":"accounts","email":"payables@acme.example","phone":"+27 11 555 0101","includeInStatements":false,"createdAt":"2026-09-16T10:00:00Z","updatedAt":"2026-09-16T11:00:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"DELETE","path":"/api/contacts/{id}/people/{personId}","summary":"Remove a person from a contact.","auth":"jwt","responseKind":"none","module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/invoices","summary":"Every document raised against this contact.","auth":"jwt","responseExample":{"invoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","documentType":"invoice","issueDate":"2026-09-01","dueDate":"2026-10-01","total":10005.0,"amountDue":10005.0,"status":"sent"}],"ageing":{"current":1.0,"days30":1.0,"days60":1.0,"days90":1.0,"overdue":1.0,"days1to30":1.0,"notYetDue":1.0},"total":42,"limit":50},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/communications?offset=0","summary":"The communication timeline — emails, WhatsApps, statements sent, plus CRM activities merged in server-side.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","channel":"email","direction":"text","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","relatedDoc":"text","status":"sent","errorMessage":"Saved.","occurredAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/communications","summary":"Log a communication by hand.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","channel":"email","direction":"text","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","relatedDoc":"text","status":"sent","errorMessage":"Saved.","occurredAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"body":{"channel":"phone","direction":"outbound","subject":"Chased the March invoice","body":"Promised payment Friday.","relatedDoc":"INV-0001"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/statement.pdf?kind=activity&from=2026-03-01&to=2027-02-28","summary":"The customer statement as a PDF: open items as at ?asOf=, or ?kind=activity&from=&to= for everything that happened on the account in a period, between an opening and a closing balance.","auth":"jwt","responseKind":"pdf","module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/send-statement","summary":"Send the statement by email or WhatsApp. By email it goes to the contact's address and to every person marked to receive statements, one email each. An open-items statement as at asOf (today when absent) is the account at that date — the customer's line on aged debtors that day; an asOf that is not a real date is refused with a 400.","auth":"jwt","responseExample":{"ok":true,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","channel":"email","outstanding":1.0,"invoiceCount":3,"failReason":"Budget deferred to the next financial year."},"body":{"channel":"email","toEmail":"accounts@karoofresh.example","asOf":"2026-09-30","kind":"activity","from":"2026-08-01","to":"2026-08-31"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PUT","path":"/api/contacts/{id}/account-stop","summary":"Put an account on stop, with a reason, or take it off. No invoice is issued to a stopped account unless someone holding invoices:approve overrides it.","auth":"jwt","body":{"stopped":true,"reason":"Cheque returned twice"},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","onStop":true,"reason":"Cheque returned twice"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/{id}/promises","summary":"Note what a debtor said they would pay and by when. A note for credit control: it moves no money.","auth":"jwt","body":{"promisedDate":"2026-11-07","note":"Sipho will pay half on Friday","amount":5000.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","promisedDate":"2026-11-07","note":"Sipho will pay half on Friday","amount":5000.0,"status":"open"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/promises/{promiseId}/close","summary":"Mark a promise dealt with, kept or not.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","promisedDate":"2026-11-07","note":"Sipho will pay half on Friday","status":"closed"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/promises","summary":"Every open promise of the active company, earliest first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","promisedDate":"2026-11-07","note":"Sipho will pay half on Friday","status":"open"}],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/aged-debtors","summary":"Aged debtors per customer in the five bands Reports draws — notYetDue, days1to30, days30 (31–60), days60 (61–90) and days90 (90+), which add up to total. current is the 0–30 roll-up (notYetDue + days1to30); overdue is everything past due.","auth":"jwt","responseExample":{"asOf":"text","rows":[{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","current":1.0,"days30":1.0,"days60":1.0,"days90":1.0,"total":10005.0,"overdue":1.0,"days1to30":1.0,"notYetDue":1.0}],"totals":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","current":1.0,"days30":1.0,"days60":1.0,"days90":1.0,"total":10005.0,"overdue":1.0,"days1to30":1.0,"notYetDue":1.0},"ledgerControlBalance":10005.0,"controlDifference":1.0},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/summary","summary":"Counts for the whole address book — by type, VIP-tagged, and customers at risk (tagged, or owing money past its due date).","auth":"jwt","responseExample":{"total":58,"customers":54,"suppliers":4,"employees":0,"practitioners":0,"starred":3,"atRisk":9},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/portal-link","summary":"The customer's self-service portal link. The token travels in the URL path, which is why this is minted rather than guessable.","auth":"jwt","responseExample":{"token":"<never returned>","url":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/invoices/{id}/portal-link/revoke","summary":"Reissue one document's customer link: every link already sent for it stops opening, and the response carries the replacement. The contact's revoke is the wider act.","auth":"jwt","responseExample":{"invoiceId":"7c2e4b10-9d3a-4f61-b8e2-5a1c0f9d3e47","portalTokenVersion":2,"token":"<token>","url":"https://app.ledgrsa.com/portal/invoice/<token>","validDays":30},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/contacts/{id}/portal-link/revoke","summary":"Retire every portal link this contact holds — the statement, the ordering portal and the link inside each of their documents — by moving the token generations on.","auth":"jwt","responseExample":{"revoked":false,"portalTokenVersion":1},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/export","summary":"The whole contact book as a CSV, in the same columns the contact import reads, plus one column per field your business defined for contacts, headed with its name — so the file comes back in through the import unchanged. Every cell is quoted and a cell that would start a spreadsheet formula is neutralised. Refused rather than cut short past the import's row limit. `contacts:export`.","auth":"jwt","responseKind":"csv","module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/consent","summary":"This contact's direct-marketing consent (POPIA section 69): where each channel — email, WhatsApp, SMS, phone — stands now, and every event recorded, newest first. No record on a channel means no consent. Invoices, statements, reminders, quotes and payslips are not marketing and are not gated by it.","auth":"jwt","responseExample":{"contactId":"3c2b1a09-8f7e-4d6c-b5a4-938271605f4e","channels":[{"channel":"email","label":"Email","mayMarket":true,"latest":{"id":"7b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","channel":"email","channelLabel":"Email","status":"given","statusLabel":"Consent given","method":"online_form","methodLabel":"Online form","note":"Ticked the newsletter box on the quote acceptance page.","recordedBy":"Thandi Mokoena","recordedAt":"2026-09-26T10:15:00Z"}},{"channel":"whatsapp","label":"WhatsApp","mayMarket":false},{"channel":"sms","label":"SMS","mayMarket":false},{"channel":"phone","label":"Phone call","mayMarket":false}],"history":[{"id":"7b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","channel":"email","channelLabel":"Email","status":"given","statusLabel":"Consent given","method":"online_form","methodLabel":"Online form","note":"Ticked the newsletter box on the quote acceptance page.","recordedBy":"Thandi Mokoena","recordedAt":"2026-09-26T10:15:00Z"}],"notMarketing":"Invoices, statements, payment reminders, quotes and payslips are not marketing and are sent whatever is recorded here."},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/consent","summary":"Record one consent event: given or withdrawn, on one channel, with how it was obtained. Never an edit — a correction is a new event, so the history cannot be rewritten. Also written to the audit log.","auth":"jwt","body":{"channel":"email","status":"given","method":"online_form","note":"Ticked the newsletter box on the quote acceptance page."},"responseExample":{"contactId":"3c2b1a09-8f7e-4d6c-b5a4-938271605f4e","channels":[{"channel":"email","label":"Email","mayMarket":true,"latest":{"id":"7b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","channel":"email","channelLabel":"Email","status":"given","statusLabel":"Consent given","method":"online_form","methodLabel":"Online form","note":"Ticked the newsletter box on the quote acceptance page.","recordedBy":"Thandi Mokoena","recordedAt":"2026-09-26T10:15:00Z"}},{"channel":"whatsapp","label":"WhatsApp","mayMarket":false},{"channel":"sms","label":"SMS","mayMarket":false},{"channel":"phone","label":"Phone call","mayMarket":false}],"history":[{"id":"7b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","channel":"email","channelLabel":"Email","status":"given","statusLabel":"Consent given","method":"online_form","methodLabel":"Online form","note":"Ticked the newsletter box on the quote acceptance page.","recordedBy":"Thandi Mokoena","recordedAt":"2026-09-26T10:15:00Z"}],"notMarketing":"Invoices, statements, payment reminders, quotes and payslips are not marketing and are sent whatever is recorded here."},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{id}/personal-data","summary":"Everything held about one person, for a POPIA access request: their contact record, every record that names them (invoices, quotes, bills, consent events, deals…) and those records' lines, as one JSON object keyed by table. Nobody else's rows. Pay records need payroll access. Needs contacts view.","auth":"jwt","responseKind":"json","module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/anonymise","summary":"Erase one person's details at their request: name, email, phones, addresses, bank details and notes are cleared, marketing consent is withdrawn on every channel, and the business's own records are kept under an anonymised name. Refused (409), naming the record and the date, while an invoice or bill naming them is inside the years the business must keep it: seven for a company, close corporation or non-profit company (Companies Act s24), five for a sole proprietor, partnership or trust (Tax Administration Act s29), the five counted from the day the return covering the record was submitted (s29(3)(a)), and with no end while no return covering it is recorded as filed. Written to the audit log. Needs contacts delete.","auth":"jwt","responseExample":{"id":"3c2b1a09-8f7e-4d6c-b5a4-938271605f4e","name":"Anonymised contact 3c2b1a09","consentWithdrawn":["email","whatsapp","sms","phone"]},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/information-officer","summary":"The information officer of the company in X-Company-Id (POPIA s55): name, email, phone and the Information Regulator registration, and the sentence a person asking about their information is given. recorded is false until one is named, and the sentence then says that under POPIA the head of the business is its information officer until another is named. Needs contacts view.","auth":"jwt","responseExample":{"companyId":"8b5d2f1e-3c4a-4e9b-a7d6-1f2e3c4b5a69","recorded":true,"name":"Naledi Dlamini","email":"privacy@karoofresh.example","phone":"0215550101","regulatorRegistration":"IRR/2026/0042","statement":"Questions about personal information go to the information officer, Naledi Dlamini (privacy@karoofresh.example, 0215550101)."},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"PUT","path":"/api/contacts/information-officer","summary":"Name the information officer of the company in X-Company-Id (POPIA s55). A name and an email address are required (400 otherwise); phone and the Information Regulator registration are optional. The officer is then named in each person's own export and in a refusal to erase their details. Written to the audit log. Needs multicompany edit, as the company profile does.","auth":"jwt","requestExample":{"name":"Naledi Dlamini","email":"privacy@karoofresh.example","phone":"0215550101","regulatorRegistration":"IRR/2026/0042"},"responseExample":{"companyId":"8b5d2f1e-3c4a-4e9b-a7d6-1f2e3c4b5a69","recorded":true,"name":"Naledi Dlamini","email":"privacy@karoofresh.example","phone":"0215550101","regulatorRegistration":"IRR/2026/0042","statement":"Questions about personal information go to the information officer, Naledi Dlamini (privacy@karoofresh.example, 0215550101)."},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/ownership-register","summary":"The securities and beneficial ownership register of the company in X-Company-Id (Companies Act s50 and s56, Companies Regulations reg 32(3)): every securities holder and beneficial owner, current and ceased, with ID numbers opened for the reader, and its dated changes, newest first, each with the date its CIPC declaration is due (10 business days on, reg 32(3A)) unless entered as already declared. statement says what the register owes CIPC now. Needs multicompany view.","auth":"jwt","responseExample":{"companyId":"8b5d2f1e-3c4a-4e9b-a7d6-1f2e3c4b5a69","entries":[{"id":"5c1e9a7b-2d3f-4e8a-9b6c-0d1e2f3a4b5c","kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":60.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","ceasedOn":null,"active":true}],"changes":[{"id":"7a2b3c4d-5e6f-4a1b-8c9d-0e1f2a3b4c5d","entryId":"5c1e9a7b-2d3f-4e8a-9b6c-0d1e2f3a4b5c","change":"ADDED","changedOn":"2026-11-02","alreadyDeclared":false,"summary":"Naledi Dlamini recorded as a beneficial owner (60.00%)","declarationDue":"2026-11-16"}],"statement":"1 beneficial owner(s) and 0 securities holder(s) are on the register. Download the declaration to file it on CIPC's portal. A recorded change is to be declared to CIPC by 2026-11-16."},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/ownership-register/declaration?asAt=2026-11-08","summary":"The CIPC beneficial ownership declaration and securities register as at asAt (default today), as a CSV to download and type into CIPC's portal (Ledgr does not file it): the company, then the beneficial owners held on that date in the order CIPC's filing asks for the fields (citizen, date of birth, ID or passport, name, surname, email, mobile, country of residence, country of origin, date of interest, interest type, percentage, address), then the securities holders in the order of CIPC's securities register template. More than ten owners adds the line that CIPC takes the rest on a disclosure form. Needs multicompany view.","auth":"jwt","responseKind":"csv","module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/ownership-register","summary":"Record a securities holder or a beneficial owner on the register of the company in X-Company-Id. A beneficial owner is a natural person (juristic true is refused) with at least one of CIPC's interest types; a shareholding or voting right needs its percentage; a securities holder needs the class and number of securities. acquiredOn is the date of interest. Unless alreadyDeclared (an interest CIPC already holds, typed in once), the change is due to CIPC within 10 business days and appears on the tax calendar as CIPC Beneficial Ownership change. The ID number is sealed at rest. Written to the audit log. Needs multicompany edit.","auth":"jwt","requestExample":{"kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":60.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","alreadyDeclared":false},"responseExample":{"id":"5c1e9a7b-2d3f-4e8a-9b6c-0d1e2f3a4b5c","kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":60.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","ceasedOn":null,"active":true},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"PUT","path":"/api/contacts/ownership-register/{entryId}","summary":"Change an interest on the register: the same body as recording one, with changedOn, the date the change took effect (required, not in the future). A ceased interest is refused. The change is dated and, unless alreadyDeclared, due to CIPC within 10 business days. Written to the audit log. Needs multicompany edit.","auth":"jwt","requestExample":{"kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":55.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","alreadyDeclared":false,"changedOn":"2026-11-05"},"responseExample":{"id":"5c1e9a7b-2d3f-4e8a-9b6c-0d1e2f3a4b5c","kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":55.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","ceasedOn":null,"active":true},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/ownership-register/{entryId}/cease","summary":"Record that an interest ended on ceasedOn (not in the future, not before it was acquired). The row stays on the register as history; the change is due to CIPC within 10 business days unless alreadyDeclared. Written to the audit log. Needs multicompany edit.","auth":"jwt","requestExample":{"ceasedOn":"2026-11-06","alreadyDeclared":false},"responseExample":{"id":"5c1e9a7b-2d3f-4e8a-9b6c-0d1e2f3a4b5c","kind":"BENEFICIAL_OWNER","juristic":false,"surname":"Dlamini","names":"Naledi","idNumber":"8001015009087","saCitizen":true,"nationality":"South Africa","countryOfResidence":"South Africa","dateOfBirth":"1980-01-01","email":"naledi@karoofresh.example","mobile":"0825550101","interestTypes":["SHAREHOLDING"],"percentage":60.0,"physicalAddress":"12 Long Street","city":"Cape Town","province":"Western Cape","postalCode":"8001","postalAddress":"PO Box 1, Cape Town, 8000","securitiesClass":"Ordinary shares","securitiesCount":60.0,"certificateNumber":"003","amountPaid":60.0,"acquiredOn":"2026-11-02","ceasedOn":"2026-11-06","active":false},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/marketing-audience?channel=email","summary":"CSV of the contacts who may be sent marketing on one channel — only those whose newest event on it is consent given. The one way a marketing list leaves Ledgr, so it can only leave through the rule. Needs contacts:export.","auth":"jwt","responseKind":"csv","module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/customer-portal?mint=false","summary":"Whether this customer is opted in to the ordering portal, their link, when they last opened it, and how many products it offers them (zero means the link opens an empty price list). Each call issues a fresh link; pass ?mint=false to read the state without issuing one. The token travels in the link's path and is redacted from every log line and error body.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customerName":"Acme Trading","enabled":false,"token":"<never returned>","url":"https://app.ledgrsa.com/customer-portal/<token>","expiresAt":"2027-09-11T08:14:00Z","lastSeenAt":"2026-09-10T14:02:11Z","offeredProductCount":240},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/customer-portal","summary":"Open or close the ordering portal for one customer. Closing also bumps their token generation, so every link already sent stops working. Opening needs the Inventory module — the portal lists the products offered from it — and is refused with 403 MODULE_NOT_LICENSED on a plan without it; closing is never refused.","auth":"jwt","body":{"enabled":true},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customerName":"Acme Trading","enabled":true,"token":"<never returned>","url":"https://app.ledgrsa.com/customer-portal/<token>","expiresAt":"2027-09-11T08:14:00Z","lastSeenAt":"2026-09-10T14:02:11Z","offeredProductCount":240},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"POST","path":"/api/contacts/{id}/customer-portal/confirms-orders","summary":"Whether this customer's ordering-portal baskets confirm themselves. On, a basket becomes a sales order at sent that holds its stock and posts nothing; a basket that would over-reserve still comes in as a draft quote naming the short item. Refused with 409 while the portal is closed, and turned off when the portal is closed. A body that cannot be read changes nothing (400). Mints no link. Requires invoices:edit.","auth":"jwt","body":{"confirmsOrders":true},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customerName":"Acme Trading","enabled":true,"token":null,"url":null,"expiresAt":null,"lastSeenAt":"2026-09-10T14:02:11Z","offeredProductCount":240,"confirmsOrders":true},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/supplier-portals","summary":"Every supplier's portal status — open or closed, and when they last opened it — in one read, with no link minted. The link is minted when somebody copies it, by GET /api/contacts/{id}/supplier-portal.","auth":"jwt","responseExample":[{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","enabled":false,"lastSeenAt":"2026-09-01T09:15:00Z"}],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"GET","path":"/api/contacts/{id}/supplier-portal","summary":"Whether this supplier is opted in to the supplier portal, and when they last signed in.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","enabled":false,"token":"<never returned>","url":"https://app.ledgrsa.com/pay/3f1a7c92","expiresAt":"2026-09-01T09:15:00Z","lastSeenAt":"2026-09-01T09:15:00Z"},"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{id}/supplier-portal","summary":"Opt a supplier in and mint their portal credential. Returned once; issuing a new one retires the old.","auth":"jwt","body":{"enabled":true},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","enabled":true,"token":"<never returned>","url":"https://app.ledgrsa.com/pay/3f1a7c92","expiresAt":"2026-09-01T09:15:00Z","lastSeenAt":"2026-09-01T09:15:00Z"},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/contacts/{contactId}/transactions?status=pending","summary":"Billable events posted against this contact by an external system, before they are invoiced.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","occurredAt":"2026-09-01T09:15:00Z","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"amount":10005.0,"currency":"ZAR","vatRate":15.0,"externalRef":"INV-0001","metadata":"text","status":"sent","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoicedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}],"module":"contacts","plan":"Free","scope":"contacts:read"},{"method":"POST","path":"/api/contacts/{contactId}/transactions/invoice","summary":"Roll this contact's pending billable events into a draft invoice.","auth":"jwt","responseExample":[{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","eventCount":3,"total":10005.0,"currency":"ZAR"}],"body":{"from":"2026-08-01","to":"2026-09-30"},"module":"contacts","plan":"Free","scope":"contacts:write"}]},{"name":"Invoicing & quotes","blurb":"Eleven document types through one engine. There is ONE layout — preview, download, email and portal all render the same HTML — and a template is a name and an accent colour.","endpoints":[{"method":"GET","path":"/api/invoices?limit=50&page=1&status=sent&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&documentType=invoice&search=cape&dateFrom=2026-03-01&dateTo=2027-02-28&requested=false","summary":"List documents. The reference paginated endpoint: SQL paging plus five child collections batch-loaded by inList. requested=true lists only what customers sent through the ordering portal.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices","summary":"Create any of the ten document types — invoice, quote, proforma, deposit, credit, debit, delivery, purchase_order, receipt, sales_order. A sales_order posts nothing and reserves its tracked lines against stock until it is converted or voided. Send a client-minted id to make the write idempotent for offline replay.","auth":"jwt","responseExample":{"id":"ed9be4c9-08ee-5ad5-bd0f-a2e2c501fb51","invoiceNumber":"INV-0042","documentType":"invoice","status":"draft","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0},"body":{"laybyFeePercent":0.0,"retentionPercent":0.0,"exportEvidenceReference":"SAD500 0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"documentType":"invoice","issueDate":"2026-08-10","dueDate":"2026-09-10","currency":"ZAR","exchangeRate":1.0,"paymentTermsDays":30,"earlyPaymentDiscountRate":0.0,"earlyPaymentDays":30,"reference":"INV-0001","notes":"Thanks for your business.","terms":"30","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"description":"Mobile app development","quantity":1.0,"unitPrice":8700.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"service","productCode":"CT-001","warehouseBin":"A-12-03"}],"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"allowCreditOverride":false,"sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","originNodeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","domesticReverseCharge":false,"forVatCorrection":false,"paymentGateways":["payfast"],"deliveryDate":"2026-09-01","shipToSiteId":null,"shipFromLocationId":null,"customFields":{},"salespersonId":null},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/{id}","summary":"One document with its lines, payments, reminders and attachments.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"GET","path":"/api/invoices/{id}/fulfilment","summary":"Where a sales order is — Open, On a trip, Part delivered, Delivered or Invoiced — read from its delivery notes and invoices, with what each line still has to deliver.","auth":"jwt","responseExample":{"state":"sent","label":"Karoo Fresh Holdings Ltd","ordered":1.0,"onATrip":1.0,"delivered":1.0,"invoiced":1.0,"openLines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","open":1.0,"unitPrice":2900.0,"vatRate":15.0}],"backordered":1.0},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/invoices/{id}","summary":"Update a document. Note it soft-deletes and re-inserts every line, so anything reading lines for a return must filter deletedAt. A draft credit or debit note takes its original tax invoice in sourceDocumentId; issuing one without it and a reason in notes is refused with a 400, VAT Act s21(3).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"laybyFeePercent":0.0,"retentionPercent":0.0,"exportEvidenceReference":"SAD500 0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentType":"invoice","declineReason":"Budget deferred to the next financial year.","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"paymentTermsDays":30,"earlyPaymentDiscountRate":0.0,"earlyPaymentDays":30,"reference":"INV-0001","notes":"Updated note.","terms":"30","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"domesticReverseCharge":true,"forVatCorrection":false,"paymentGateways":["payfast"],"deliveryDate":"2026-09-01","shipToSiteId":null,"shipFromLocationId":null,"customFields":{}},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/invoices/{id}","summary":"Void a document. Sets the status; nothing leaves history. An issued tax invoice, credit note or debit note is refused with a 409 naming the note that corrects it.","auth":"jwt","responseExample":{"ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/summary","summary":"The KPI row — outstanding, overdue, paid this month, and drafts.","auth":"jwt","responseExample":{"outstanding":1.0,"overdue":1.0,"paid30":1.0,"draftTotal":10005.0,"quotesOpen":1,"documentCount":3},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/send","summary":"Mark sent and deliver by email or WhatsApp, with the PDF attached if the tenant's settings say so. Send your own clientId (a UUID) and a retry after a lost response reports the send already made instead of sending it again. A credit or debit note is refused with a 400 until it names its original tax invoice (sourceDocumentId) and a reason (notes), VAT Act s21(3).","auth":"jwt","body":{"channel":"email","clientId":"8b2d6f14-3c7a-4e95-b0d2-71a9e5c3f640","allowCreditOverride":false},"responseExample":{"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"channel":"email","delivered":true,"deliveryError":"text","portalUrl":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/bulk-send","summary":"Email several documents at once. Each goes through the single send (a draft is issued, the PDF attached when the settings say so, the delivery recorded on it); a voided document is skipped. Answers what happened to each one. Re-send the same batchId to retry: a document this batch already delivered is not emailed again. Email only; at most 100 documents. Requires invoices:edit.","auth":"jwt","body":{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ids":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"channel":"email"},"responseExample":{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","customer":"Karoo Fresh Holdings Ltd","outcome":"text","reason":"Budget deferred to the next financial year."}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/bulk-pdf","summary":"Several documents as ONE PDF, in the order asked for, each starting on its own page — for printing or keeping. Documents not in the active company are left out; the X-Ledgr-Documents-Included header says how many are in it. At most 50. Requires invoices:view.","auth":"jwt","responseKind":"pdf","body":{"ids":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/payments","summary":"Record a payment. Moves the document to partial or paid and advances any CRM deal linked to it. A payment above the balance is refused unless keepAsCredit names the excess, to the cent: then the document is settled and the excess is kept as the customer's credit for a later invoice (see apply-credit), and the receipt is banked in full. On an issued credit note the same call records a refund: money paid back to the customer, never more than is still owed back, which moves the credit note to partial or paid (shown as part refunded or refunded) and posts DR trade receivables / CR bank. A draft credit note is refused (issue it first), and a refund cannot keep or spend customer credit. Nothing is sent through a payment gateway.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"amount":51750.0,"method":"EFT","date":"2026-08-12","reference":"FNB 4472","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exchangeRate":1.0,"keepAsCredit":null,"bankAccountId":"8d2e4b17-6c3a-4f90-b5e1-7a9c0d3f2b64"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/invoices/{id}/payments/{paymentId}","summary":"Withdraw a receipt keyed by hand. Reverses it in the ledger, recomputes what the document owes from the surviving payments, and audits at warning. Refused for a Yoco or PayFast receipt (refund through the gateway), a bank-matched one (unmatch the statement line) and an applied deposit (raise a credit note).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/{id}/customer-credit","summary":"The credit this invoice's customer holds — money they overpaid on an earlier invoice and chose to keep for the next one, and what is still owed back on their issued credit notes — in this invoice's currency and company, and how much of it this invoice can take (the smaller of the credit and what it still owes; nothing on a document that cannot take a payment).","auth":"jwt","responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customerName":"Karoo Fresh Holdings Ltd","currency":"ZAR","available":1.0,"amountDue":10005.0,"applicable":1.0,"refundable":1.0},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/apply-credit","summary":"Settle part or all of this invoice from the customer's credit. Refused for more than the customer holds in this currency or more than the invoice still owes. Moves no cash: the credit already sits in Trade Receivables, so no bank leg is posted. Spends the oldest credit first; removing the resulting payment line restores the credit. Send your own clientId (a UUID) and a re-sent request applies the credit once. An issued credit note with something still owed back is credit too: applying it lowers what the credit note owes back by the same amount, and removing the application from the invoice gives it back.","auth":"jwt","body":{"amount":250.0,"clientId":"c41e9a07-6b2d-4f8e-a3d1-5e70b9c2f816"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","deliveryDate":"2026-09-01","expectedPaymentDate":"2026-09-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","lastSendChannel":"email","lastSendDelivered":true,"lastSendError":"text","lastSendAt":"2026-09-01T09:15:00Z","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z","status":"sent"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","domesticReverseCharge":false,"paymentGateways":["payfast"]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/customer-credit/refund","summary":"Pay back credit this invoice's customer holds from their own payments (money they overpaid and chose to keep, or paid on account). Posts debit Trade Receivables, credit the bank account named by bankAccountId (the pooled bank when absent) on date, which is never ahead of today and never before the money arrived, and writes a debit line on that account; no sale is reversed and no VAT moves. Pays back the oldest credit first. Refused for more than the customer holds from their payments by that date (a credit note's own credit is refunded on the credit note). Removing the resulting payment line restores the credit. Send your own clientId (a UUID) and a re-sent request pays back once. Needs invoices:edit.","auth":"jwt","body":{"amount":350.0,"date":"2026-10-28","bankAccountId":"8d2e4b17-6c3a-4f90-b5e1-7a9c0d3f2b64","reference":"Refund EFT","clientId":"c41e9a07-6b2d-4f8e-a3d1-5e70b9c2f816"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","deliveryDate":"2026-09-01","expectedPaymentDate":"2026-09-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","lastSendChannel":"email","lastSendDelivered":true,"lastSendError":"text","lastSendAt":"2026-09-01T09:15:00Z","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z","status":"sent"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","domesticReverseCharge":false,"paymentGateways":["payfast"]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/convert","summary":"Convert a quote, pro-forma or sales order into a draft tax invoice with the same lines. Mints the invoice number; the invoice posts and takes its stock when it is issued. Converting a sales order releases what it reserved. A quote or pro-forma can instead be invoiced in parts: send percent (a share of every line) or lines (chosen line ids with quantities); each part is its own draft tax invoice, a part asking for more than is left answers 409 naming the figures, and the quote reads invoiced once nothing is left. With neither field, a part-invoiced quote invoices what is left. A clientId makes the call replay-safe: a retry answers 200 with the invoice the first call raised.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"terms":"30","dueDate":"2026-09-01","paymentTermsDays":30,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","percent":null,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":2.0}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/{id}/progress","summary":"What has been invoiced against a quote or pro-forma: the quote's total, the sum of the live invoices raised from it, each line's quantity invoiced and still to invoice, and the invoices themselves. Voided and deleted invoices give their part back.","auth":"jwt","responseExample":{"quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"QUO-0001","currency":"ZAR","quoteTotal":10005.0,"invoicedTotal":4002.0,"fullyInvoiced":false,"partlyInvoiced":true,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"invoicedQuantity":1.2,"remainingQuantity":1.8,"unitPrice":2900.0}],"invoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","total":4002.0,"issueDate":"2026-09-01"}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"GET","path":"/api/invoices/{id}/layby","summary":"A lay-by's money: its price, what is held (the customer's money until the goods are delivered), what is still owed, the cancellation fee agreed when it was made (at most 1% of the price), what cancelling now would keep and refund, and every payment, application, fee and refund.","auth":"jwt","responseExample":{"laybyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","status":"sent","total":10005.0,"held":1.0,"stillOwed":1.0,"feePercent":15.0,"feeIfCancelledNow":1.0,"refundIfCancelledNow":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceNumber":"INV-0001"}],"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/layby/payments","summary":"Take a payment towards an issued lay-by into a bank account. Held in Lay-by Payments Held (2157), never revenue; refused on a draft, past the price, or once collected or cancelled.","auth":"jwt","requestExample":{"amount":500.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","method":"cash","on":"2026-10-14","reference":"Till slip 1042"},"responseExample":{"laybyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","status":"sent","total":10005.0,"held":1.0,"stillOwed":1.0,"feePercent":15.0,"feeIfCancelledNow":1.0,"refundIfCancelledNow":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceNumber":"INV-0001"}],"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/layby/collect","summary":"Collect a lay-by paid in full: its goods are issued on a tax invoice dated the collection, taken out of stock, and the invoice is settled from what was held. Refused before it is paid in full, and a second time.","auth":"jwt","requestExample":{"on":"2026-10-14"},"responseExample":{"laybyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","status":"sent","total":10005.0,"held":1.0,"stillOwed":1.0,"feePercent":15.0,"feeIfCancelledNow":1.0,"refundIfCancelledNow":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceNumber":"INV-0001"}],"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/layby/cancel","summary":"Cancel a lay-by: the agreed fee is kept on its own invoice (unless waived for death or hospitalisation) and the rest is refunded from the bank account given; the goods are released.","auth":"jwt","requestExample":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","on":"2026-10-14","waiveFee":false,"reason":"Customer changed their mind"},"responseExample":{"laybyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","status":"sent","total":10005.0,"held":1.0,"stillOwed":1.0,"feePercent":15.0,"feeIfCancelledNow":1.0,"refundIfCancelledNow":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceNumber":"INV-0001"}],"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/instalment-credit?page=1&limit=50","summary":"Every instalment credit agreement of the company, newest delivery first: the customer, the cash price, what is owed today and the next instalment's date.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"balance":10005.0,"nextDueOn":"2026-09-01"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"GET","path":"/api/invoices/{id}/instalment-credit","summary":"The instalment credit agreement on an invoice: its terms and National Credit Act particulars (cost of credit, total payable, the rate and its regulation 42 cap), the schedule with each month's finance charge, and the statement of account.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit/quote","summary":"The pre-agreement quote on an issued tax invoice (National Credit Act s92): the schedule, the cost of credit and the total payable. Nothing is written. A rate above the regulation 42 cap for the credit type (the repo rate plus 17% for an instalment agreement), an initiation fee above regulation 42(2) and 43(3) or a service fee above R60 a month is refused, naming the cap.","auth":"jwt","requestExample":{"depositAmount":1000.0,"termMonths":12,"annualRatePercent":21.0,"referenceRatePercent":7.25,"creditType":"other","initiationFee":0.0,"monthlyServiceFee":0.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","method":"eft"},"responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"monthlyRatePercent":15.0,"referenceRatePercent":15.0,"creditType":"standard","creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"totalInterest":10005.0,"totalFees":10005.0,"costOfCredit":10005.0,"totalPayable":10005.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit","summary":"Conclude the agreement at delivery: the tax invoice is settled in full - the deposit into the bank account given, the rest financed into Instalment Credit Receivable (1328) - so the VAT on the whole cash value is declared now on either accounting basis (VAT Act s9(3)(c)). Refused on a draft, a foreign-currency invoice or one already paid towards, and above the caps.","auth":"jwt","requestExample":{"depositAmount":1000.0,"termMonths":12,"annualRatePercent":21.0,"referenceRatePercent":7.25,"creditType":"other","initiationFee":0.0,"monthlyServiceFee":0.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","method":"eft"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit/charges","summary":"Earn every month's finance charge falling due by the date given (today when omitted): the principal outstanding times the monthly rate, on its own exempt document (VAT201 field 3), with the month's service fee beside it at the standard rate.","auth":"jwt","requestExample":{"through":"2026-10-15"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit/instalments","summary":"Record an instalment into a bank account: the month's charge is earned first, then the money pays interest, then fees, then the principal (National Credit Act s126(3)). Refused above what is owed today; the agreement reads settled once nothing is.","auth":"jwt","requestExample":{"amount":1070.82,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","on":"2026-11-15","method":"eft","reference":"Debit order November"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit/write-off","summary":"Write off what is still owed as irrecoverable (VAT Act s22(1)): the cash value not recovered claims back its VAT at the invoice's tax fraction (field 17) and the unpaid charge documents are written off. Refused once the goods are repossessed.","auth":"jwt","requestExample":{"on":"2026-11-20","reason":"Customer emigrated, untraceable"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/instalment-credit/repossess","summary":"The goods repossessed or surrendered (VAT Act s8(10)): the tax fraction of the cash value not recovered (s10(16)) is deducted as input tax (field 15) and the rest of the principal is a loss; count the goods back into stock with a stock adjustment.","auth":"jwt","requestExample":{"on":"2026-11-20","reason":"Three-seater sofa, grey, collected from the customer","how":"repossessed","customerIsVendor":false},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","status":"sent","deliveredOn":"2026-09-01","cashPrice":10005.0,"vatInCashPrice":1305.0,"deposit":1.0,"principalDebt":1.0,"termMonths":1,"annualRatePercent":15.0,"referenceRatePercent":15.0,"creditTypeLabel":"Karoo Fresh Holdings Ltd","maximumRatePercent":15.0,"initiationFee":1.0,"monthlyServiceFee":1.0,"instalment":1.0,"costOfCredit":10005.0,"totalPayable":10005.0,"principalOutstanding":1.0,"chargesOutstanding":1.0,"balance":10005.0,"paidToDate":1.0,"nextDueOn":"2026-09-01","nextInstalment":1.0,"schedule":[{"number":1,"dueOn":"2026-09-01","instalment":1.0,"interest":1.0,"fees":1.0,"capital":1.0,"balanceAfter":10005.0,"charged":false,"chargeNumber":"INV-0001"}],"statement":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","on":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"balanceAfter":10005.0,"documentNumber":"INV-0001"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/gift-vouchers?status=active","summary":"The company's gift vouchers, newest first, beside the voucher book's total and the ledger's 2159 Gift Vouchers Outstanding with their difference. ?status=active|spent|expired narrows the list.","auth":"jwt","responseExample":{"vouchers":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"GV-7F3A9C21","faceValue":500.0,"balance":350.0,"status":"active","issuedOn":"2026-10-01","expiresOn":"2029-10-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movements":[]}],"outstanding":350.0,"ledgerBalance":350.0,"difference":0.0},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/gift-vouchers","summary":"Sell a face-value gift voucher into a bank account. Held in Gift Vouchers Outstanding (2159) with no VAT and no revenue: the sale is disregarded (VAT Act s10(18)) and the money is the bearer's until it is spent. The term is three years from sale unless longer; a shorter one is refused (Consumer Protection Act s63(2)).","auth":"jwt","requestExample":{"faceValue":500.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","issuedOn":"2026-10-01","expiresOn":"2029-10-01","code":"GV-7F3A9C21","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"GV-7F3A9C21","faceValue":500.0,"balance":500.0,"status":"active","issuedOn":"2026-10-01","expiresOn":"2029-10-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movements":[{"kind":"issued","amount":500.0,"on":"2026-10-01"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/gift-vouchers/{id}","summary":"One voucher with every movement: sold, spent on which invoice, lapsed.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"GV-7F3A9C21","faceValue":500.0,"balance":350.0,"status":"active","issuedOn":"2026-10-01","expiresOn":"2029-10-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movements":[{"kind":"issued","amount":500.0,"on":"2026-10-01"},{"kind":"redeemed","amount":150.0,"on":"2026-10-14","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0042"}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/gift-vouchers/{id}/redeem","summary":"Spend part or all of a voucher on an issued tax invoice (DR 2159 / CR 1320, no bank leg). The VAT is the invoice's, on its own date - the supply of the goods or services is made now. Refused on a draft or void invoice, past the voucher's balance or the invoice's amount due, and after the voucher's term.","auth":"jwt","requestExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":150.0,"on":"2026-10-14"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"GV-7F3A9C21","faceValue":500.0,"balance":350.0,"status":"active","issuedOn":"2026-10-01","expiresOn":"2029-10-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movements":[{"kind":"issued","amount":500.0,"on":"2026-10-01"},{"kind":"redeemed","amount":150.0,"on":"2026-10-14","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0042"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/gift-vouchers/{id}/expire","summary":"Let what is left of a voucher lapse once its term is over: DR 2159 / CR 4140 Sundry Income, with no VAT (no supply was ever made). Refused while the voucher is still good.","auth":"jwt","requestExample":{"on":"2029-10-02"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"GV-7F3A9C21","faceValue":500.0,"balance":0.0,"status":"expired","issuedOn":"2026-10-01","expiresOn":"2029-10-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","movements":[{"kind":"issued","amount":500.0,"on":"2026-10-01"},{"kind":"redeemed","amount":150.0,"on":"2026-10-14","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0042"},{"kind":"expired","amount":350.0,"on":"2029-10-02"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/retention/release","summary":"Release retention held on a contract invoiced from this quote in parts: half of what was withheld at practical completion (stage practical_completion), everything still held at the end of the defects period (stage final), or an explicit amount before VAT. Raised as a draft invoice that charges VAT on the release; more than is held is refused with 400.","auth":"jwt","requestExample":{"stage":"practical_completion","amount":null},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","deliveryDate":"2026-09-01","shipToSiteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","shipToAddress":"12 Long Street, Cape Town, 8001","shipFromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","shipFromReason":"Budget deferred to the next financial year.","expectedPaymentDate":"2026-09-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","paymentTermsDays":30,"sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","customerFirstViewedAt":"2026-09-01T09:15:00Z","customerLastViewedAt":"2026-09-01T09:15:00Z","requestedByCustomer":false,"internalNote":"Budget deferred to the next financial year.","lastSendChannel":"email","lastSendDelivered":true,"lastSendError":"text","lastSendAt":"2026-09-01T09:15:00Z","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockWarnings":["text"],"fulfilment":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","awaitingBank":false}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z","status":"sent","deliveryStatus":"sent"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"retentionPercent":15.0,"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","domesticReverseCharge":false,"paymentGateways":["payfast"],"changeNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","customFields":{"key":"text"}},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/apply-deposit","summary":"Apply a deposit invoice against the final invoice, releasing it from Deferred Revenue (2150).","auth":"jwt","responseExample":{"depositId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","depositAppliedTo":"2026-09-30","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","newInvoiceStatus":"sent","amount":10005.0},"body":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/reminders","summary":"Send a payment reminder now, outside the configured schedule. Send your own clientId (a UUID) and a retry after a lost response reports the reminder already sent instead of sending it again.","auth":"jwt","body":{"channel":"email","clientId":"c41e9a07-6b2d-4f8e-a3d1-5e70b9c2f816"},"responseExample":{"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","invoiceNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","dueDate":"2026-10-01","currency":"ZAR","exchangeRate":1.0,"subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"total":10005.0,"amountPaid":0.0,"amountDue":10005.0,"vatRegistered":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","terms":"30","sourceDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"discountRate":0.0,"vatRate":15.0,"vatInclusive":false,"lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0,"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","discountType":"PERCENT","discountFixed":0.0,"kind":"PRODUCT","productCode":"CT-001","warehouseBin":"A-12-03"}],"payments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"method":"eft","reference":"INV-0001","createdAt":"2026-09-01T09:15:00Z"}],"reminders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sentDate":"2026-09-01","channel":"email","createdAt":"2026-09-01T09:15:00Z"}],"contactRemindersPaused":false,"tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","deposit":{"percent":15.0,"amount":10005.0,"appliedTo":"2026-09-30"},"picking":{"warehouse":"Cape Town HQ","picker":"Thandi Mokoena","lines":[{"idx":1,"picked":true}]},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"channel":"email","delivered":true,"deliveryError":"text","portalUrl":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/{id}/bad-debts","summary":"Write a debt off as bad, or record a recovery of one, on the invoice itself — on every plan with Invoicing. `bad_debt_written_off` writes `amount` (at most the amount due) off: DR 6300 Bad debts / CR 1320, and only when the company is a VAT vendor on `date` and the invoice charged VAT is the invoice's own VAT share claimed back as well (DR 1340, VAT201 field 17); a company that is not a vendor claims nothing (`vatAmount` 0). Needs invoices:approve and is audited as `invoice.bad_debt_written_off`. `bad_debt_recovered` reinstates up to what was written off (DR 1320 / CR 6300, and CR 2130 at the same fraction only where the write-off claimed VAT) so the customer's payment is then recorded as usual; needs invoices:edit. A blank reason, more than is owed or written off, and a vendor's debt on the payments basis are refused.","auth":"jwt","body":{"kind":"bad_debt_written_off","amount":11500.0,"date":"2026-09-30","reason":"Customer liquidated; claim lodged with the liquidator","documentRef":"Liquidator's letter 2026/118"},"responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000001","kind":"bad_debt_written_off","kindLabel":"Bad debt written off","field":"17","date":"2026-09-30","invoiceId":"7f6c1a2e-0000-4000-8000-000000000002","invoiceNumber":"INV-0042","consideration":11500.0,"vatAmount":1500.0,"reason":"Customer liquidated; claim lodged with the liquidator","documentRef":"Liquidator's letter 2026/118"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"PUT","path":"/api/invoices/{id}/expected-payment-date","summary":"Record the date the customer has promised to pay, or send null to clear it. The cash-flow forecast places an overdue invoice on this date instead of leaving it out — but only while the date is today or later, so a promise that has come and gone falls back to the due date. Nothing is ever inferred: an invoice with no promise stays in the overdue figure reported beside the forecast. Writes one column and nothing else, so no line is rewritten and no journal is re-posted.","auth":"jwt","body":{"expectedPaymentDate":"2026-10-15"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","dueDate":"2026-09-01","expectedPaymentDate":"2026-10-15","forecastDate":"2026-10-15"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/{id}/payment-links","summary":"Payment links already minted for this document.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","gateway":"payfast","url":"https://app.ledgrsa.com/pay/3f1a7c92","amountCents":49900,"currency":"ZAR","status":"sent","expiresAt":"2026-09-01T09:15:00Z","paidAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/payment-links","summary":"Mint a Ledgr /pay/{linkId} URL that builds and signs a PayFast checkout at request time. PayFast only — Yoco is refused, because it has no server-side call to obtain a checkout.","auth":"jwt","responseExample":{"id":"acc6ca52-1ef9-5d6e-8638-5a7c33f1f3dc","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","gateway":"payfast","url":"https://www.ledgrsa.com/pay/<id>","status":"pending","expiresAt":"2026-09-10T00:00:00Z","createdAt":"2026-09-01T09:00:00Z"},"body":{"gateway":"payfast","amountCents":49900,"expiresAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/pdf","summary":"Render a document to PDF server-side, from the same HTML the preview and the portal use.","auth":"jwt","responseKind":"pdf","body":{"earlyPaymentDiscountRate":2.0,"earlyPaymentBy":"2026-10-24","docType":"invoice","docTitle":"Karoo Fresh Holdings Ltd","number":"INV-0001","date":"2026-09-30","due":"2026-10-31","status":"sent","customerReference":"PO-4471","originalNumber":"INV-0042","originalDate":"2026-08-14","vatRegistered":true,"currencyCode":"ZAR","currencySymbol":"R","sender":{"name":"Karoo Fresh Holdings Ltd","address":"12 Long Street, Cape Town, 8001","vatNumber":"4123456789","email":"accounts@karoofresh.example","registrationNumber":"2021/123456/07"},"client":{"name":"Karoo Fresh Holdings Ltd","address":"12 Long Street, Cape Town, 8001","vatNumber":"4123456789","email":"accounts@karoofresh.example","registrationNumber":"2021/123456/07"},"lines":[{"description":"Captured during the August review","code":"CT-001","quantity":2.0,"unitPrice":1500.0,"discount":0.0,"discountIsPercent":true,"vatPercent":15.0,"lineTotal":1500.0,"kind":"PRODUCT","unit":"each"}],"subtotal":1500.0,"discountTotal":0.0,"vatTotal":15.0,"total":1500.0,"notes":"Budget deferred to the next financial year.","tcs":"Goods remain the property of the seller until paid in full.","bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","templateColorHex":"#0D47A1","primaryLogoSrc":"https://app.ledgrsa.com/files/logo.png","associationLogoSrc":"https://app.ledgrsa.com/files/association.png","show":{"dueDate":true,"contactName":true,"businessAddress":true,"vatNumber":true,"discountColumn":true,"associationLogo":true,"paymentLinks":true},"labels":{"description":"Description","qty":"Qty","rate":"Rate","discount":"Discount","tax":"VAT","total":"Total","hours":"Hours","grandTotal":"R 1 150.00"},"depositPercent":15.0,"depositAmount":10005.0,"paymentGateways":["payfast"],"amountPaid":0.0,"amountDue":1500.0,"paidDeposits":[],"depositVat":{},"paymentMethod":"eft","paymentDate":"2026-09-01","domesticReverseCharge":false,"randFigures":null,"formats":{"date":"DAY_MONTH_YEAR","number":"SPACE_POINT"},"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workSignOff":{"jobNumber":"JC-0001","signedBy":"Thandi Mokoena","role":"Accountant","signedOn":"2026-09-01","signatureSrc":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="},"customFields":[{"label":"Site reference","value":"Sandton Gate, Block C"}],"language":"af"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/property-sales","summary":"The company's sales of fixed property (T-7.20): each with its VAT treatment, its s9(3)(d) time of supply and rate, its payments and the output tax each declared. Needs invoices:view.","auth":"jwt","responseExample":{"sales":[{"id":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"treatment":"vat","treatmentNote":"A taxable supply by a VAT vendor: VAT is charged and the buyer pays no transfer duty (Transfer Duty Act s9(15)).","heldAs":"stock","fixedAssetId":null,"capitalGoods":false,"residentialPriceFixed":false,"timeOfSupply":"2026-08-15","ratePercent":15.0,"rateReason":"s9(3)(d): the rate on the time of supply","registeredOn":null,"payments":[{"id":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false,"declaredOn":"2026-08-15","vatAmount":15000.0}],"received":115000.0,"vatDeclared":15000.0}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/property-sales","summary":"Record the written agreement of a sale of fixed property. A VAT vendor's sale is a taxable supply (no transfer duty, Transfer Duty Act s9(15)); a seller that is not a vendor on the agreement date charges no VAT and the buyer pays transfer duty; `goingConcern` zero-rates an enterprise sold as a going concern only when all five s11(1)(e) terms are true. `heldAs` stock names the account carrying the property's cost and that cost; asset names the fixed asset. `residentialPriceFixed` is the s67A(4) answer. Needs invoices:create.","auth":"jwt","body":{"clientId":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"heldAs":"stock","fixedAssetId":null,"stockAccountCode":"1395","costOfSale":800000.0,"residentialPriceFixed":false,"goingConcern":null},"responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"treatment":"vat","treatmentNote":"A taxable supply by a VAT vendor: VAT is charged and the buyer pays no transfer duty (Transfer Duty Act s9(15)).","heldAs":"stock","fixedAssetId":null,"capitalGoods":false,"residentialPriceFixed":false,"timeOfSupply":"2026-08-15","ratePercent":15.0,"rateReason":"s9(3)(d): the rate on the time of supply","registeredOn":null,"payments":[{"id":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false,"declaredOn":"2026-08-15","vatAmount":15000.0}],"received":115000.0,"vatDeclared":15000.0},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/property-sales/{id}","summary":"One sale of fixed property, its payments and the output tax declared. Needs invoices:view.","auth":"jwt","responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"treatment":"vat","treatmentNote":"A taxable supply by a VAT vendor: VAT is charged and the buyer pays no transfer duty (Transfer Duty Act s9(15)).","heldAs":"stock","fixedAssetId":null,"capitalGoods":false,"residentialPriceFixed":false,"timeOfSupply":"2026-08-15","ratePercent":15.0,"rateReason":"s9(3)(d): the rate on the time of supply","registeredOn":null,"payments":[{"id":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false,"declaredOn":"2026-08-15","vatAmount":15000.0}],"received":115000.0,"vatDeclared":15000.0},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/property-sales/{id}/payments","summary":"A payment of the price. The first payment the seller can apply is the time of supply (s9(3)(d)) and fixes the rate (s67A); its tax fraction is declared in the period it is received (s16(4), VAT404 4.5.2): DR bank, CR 2130, CR 2150. Money a conveyancer or agent holds in trust (`heldInTrust`) is not yet a payment and is declared when paid over on registration. Refused above the price or after registration. Needs invoices:edit.","auth":"jwt","body":{"clientId":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false},"responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"treatment":"vat","treatmentNote":"A taxable supply by a VAT vendor: VAT is charged and the buyer pays no transfer duty (Transfer Duty Act s9(15)).","heldAs":"stock","fixedAssetId":null,"capitalGoods":false,"residentialPriceFixed":false,"timeOfSupply":"2026-08-15","ratePercent":15.0,"rateReason":"s9(3)(d): the rate on the time of supply","registeredOn":null,"payments":[{"id":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false,"declaredOn":"2026-08-15","vatAmount":15000.0}],"received":115000.0,"vatDeclared":15000.0},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/property-sales/{id}/registration","summary":"Transfer registered in the Deeds Office, with `balancePaid` the rest of the price paid over then (money held in trust included; the whole price must then be paid). Settles the rate with s67A(2), declares the tax still owed, recognises the price less its VAT as revenue (sales 4010 against the cost of sale for stock; profit or loss on disposal for a fixed asset, which leaves the register) and declares it in VAT201 fields 1/4 (1A/4A for a fixed asset, field 2 for a going concern). Needs invoices:edit.","auth":"jwt","body":{"registeredOn":"2026-10-20","balancePaid":1035000.0},"responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000020","property":"Erf 412, Stellenbosch","buyer":"T Mokoena","agreementDate":"2026-08-01","price":1150000.0,"treatment":"vat","treatmentNote":"A taxable supply by a VAT vendor: VAT is charged and the buyer pays no transfer duty (Transfer Duty Act s9(15)).","heldAs":"stock","fixedAssetId":null,"capitalGoods":false,"residentialPriceFixed":false,"timeOfSupply":"2026-08-15","ratePercent":15.0,"rateReason":"s9(3)(d): the rate on the time of supply","registeredOn":null,"payments":[{"id":"7f6c1a2e-0000-4000-8000-000000000021","paidOn":"2026-08-15","amount":115000.0,"heldInTrust":false,"declaredOn":"2026-08-15","vatAmount":15000.0}],"received":115000.0,"vatDeclared":15000.0},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/number-leases?docType=invoice&nodeId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Document-number leases this device holds, so that a device can mint real series numbers offline; DocumentNumbering still uses its own local lease and never asks for one.","auth":"jwt","responseExample":[{"leaseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docType":"standard","nodeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","prefix":"INV-","year":2026,"padLength":3,"rangeStart":1,"rangeEnd":1,"nextLocal":1,"issuedAt":"2026-09-01T09:15:00Z","expiresAt":"2026-09-01T09:15:00Z","status":"sent","firstNumber":"INV-0001","lastNumber":"INV-0001"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/number-leases","summary":"Reserve a block of numbers in a series.","auth":"jwt","responseExample":{"leaseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docType":"standard","nodeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","prefix":"INV-","year":2026,"padLength":3,"rangeStart":1,"rangeEnd":1,"nextLocal":1,"issuedAt":"2026-09-01T09:15:00Z","expiresAt":"2026-09-01T09:15:00Z","status":"sent","firstNumber":"INV-0001","lastNumber":"INV-0001"},"body":{"docType":"invoice","nodeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","size":25},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/invoices/number-leases/release","summary":"Give an unused block back so the numbers are not burned.","auth":"jwt","responseExample":{"released":1},"body":{"docType":"invoice","nodeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/recurring","summary":"Recurring invoice schedules.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/recurring","summary":"Create a recurring schedule from a template document.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"body":{"collectAutomatically":false,"billsAhead":false,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentType":"invoice","description":"Captured during the August review","currency":"ZAR","amount":1500.0,"frequency":"monthly","nextDate":"2026-09-30","endDate":"2026-09-30","paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","terms":"30","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","onCreate":"email","vatType":"exempt","lines":[{"description":"Office cleaning","quantity":3.0,"unitPrice":200.0,"discountRate":10.0,"discountType":"PERCENT","vatRate":15.0,"kind":"SERVICE","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},{"description":"Delivery of consumables","quantity":1.0,"unitPrice":100.0,"vatRate":0.0,"vatType":"zero_local"}],"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tcs":"Payable within 30 days.","bankDetails":"FNB Cheque 62812345678","footer":"Thank you for your business"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/recurring/{id}","summary":"One schedule and its issue history.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","documentType":"invoice","description":"Consulting services — August 2026","currency":"ZAR","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","terms":"30","active":true,"lastGeneratedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/recurring/{id}","summary":"Change a schedule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"body":{"collectAutomatically":false,"billsAhead":false,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","currency":"ZAR","amount":10005.0,"frequency":"quarterly","nextDate":"2026-09-01","endDate":"2026-09-30","paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","terms":"30","active":true,"onCreate":"email","vatType":"exempt","lines":[{"description":"Office cleaning","quantity":3.0,"unitPrice":200.0,"discountRate":10.0,"discountType":"PERCENT","vatRate":15.0,"kind":"SERVICE","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},{"description":"Delivery of consumables","quantity":1.0,"unitPrice":100.0,"vatRate":0.0,"vatType":"zero_local"}],"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tcs":"Payable within 30 days.","bankDetails":"FNB Cheque 62812345678","footer":"Thank you for your business"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/recurring/{id}","summary":"Delete a schedule. Documents it has already raised are untouched.","auth":"jwt","responseKind":"none","module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/recurring/{id}/toggle","summary":"Pause or resume a schedule.","auth":"jwt","body":{"active":false},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/recurring/{id}/advance","summary":"Skip a cycle: move the schedule one cycle on WITHOUT raising its document, stepped from its anchor exactly as the scheduled run steps it. The anchor never moves, so a schedule on the 31st that lands on 28 February is back on the 31st in March. To raise the cycle's document and move on, use POST /api/recurring/{id}/run.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-09-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/recurring/{id}/run","summary":"Run now: raise this cycle's document exactly as the scheduled run raises it — the schedule's own amount (VAT-inclusive), document type, payment terms and notes — and move the schedule one cycle on, in one transaction. Refused with 409 on a paused schedule or one another run has just moved on, and with the Free-plan quota's 403 when the month's allowance is used.","auth":"jwt","responseExample":{"schedule":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","amount":10005.0,"frequency":"monthly","nextDate":"2026-10-01","active":true,"currency":"ZAR","documentType":"invoice","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","onCreate":"email"},"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0042","sentBy":"email","delivered":true},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoice-templates","summary":"The tenant's templates plus the five presets. A template is a name and an accent colour — the layout is fixed and there is exactly one.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","primaryColour":"#0D47A1"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoice-templates","summary":"Add a template. Only name and colour are accepted; the legacy layout_json, secondary_colour, show_logo, show_signature and footer_text columns are read by nothing and no longer accepted.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","primaryColour":"#0D47A1"},"body":{"name":"Site works","isDefault":false,"primaryColour":"#00838F"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoice-templates/{id}","summary":"One template.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isDefault":true,"primaryColour":"#0D47A1","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/invoice-templates/{id}","summary":"Rename or recolour a template.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","primaryColour":"#0D47A1"},"body":{"name":"Site works","isDefault":true,"primaryColour":"#0D47A1"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/invoice-templates/{id}","summary":"Remove a tenant template. The five presets cannot be removed.","auth":"jwt","responseKind":"none","module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoice-settings","summary":"The seven-tab settings centre — numbering, labels, field visibility, email templates, branding, defaults and auto-reconciliation.","auth":"jwt","responseExample":{"numbering":{"invoice":{"prefix":"INV-","next":1}},"labels":{"docTitle":{"invoice":"Tax Invoice"},"description":"Consulting services — August 2026","qty":"text","unitPrice":"text","rate":"text","hours":"text","discount":"text","tax":"text","net":"text","total":"text"},"show":{"dueDate":true,"contactName":true,"businessAddress":true,"vatNumber":true,"discountColumn":true,"paymentLinks":true,"associationLogo":true},"email":{"replyTo":"2026-09-30","ccSelf":true,"attachPdf":true,"templates":{"invoice":{"subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached."}}},"logos":{"primaryName":"Karoo Fresh Holdings Ltd","primaryDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","primaryAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","associationName":"Karoo Fresh Holdings Ltd","associationDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","associationAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"defaults":{"bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year."},"autoRecon":{"enabled":true,"yoco":true,"payfast":true,"matchToleranceZar":1.0},"activeTemplateName":"Karoo Fresh Holdings Ltd"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoice-settings/logo?slot=primary&name=logo.png","summary":"Upload a company or association logo. Raw image bytes with ?slot=primary|association; the server recompresses, stores it in Cloud Storage and files the attachment id against the tenant's settings, so nothing needs saving afterwards.","auth":"jwt","responseExample":{"slot":"text","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"PUT","path":"/api/invoice-settings","summary":"Replace the invoice settings.","auth":"jwt","responseExample":{"numbering":{"invoice":{"prefix":"INV-","next":1}},"labels":{"docTitle":{"invoice":"Tax Invoice"},"description":"Consulting services — August 2026","qty":"text","unitPrice":"text","rate":"text","hours":"text","discount":"text","tax":"text","net":"text","total":"text"},"show":{"dueDate":true,"contactName":true,"businessAddress":true,"vatNumber":true,"discountColumn":true,"paymentLinks":true,"associationLogo":true},"email":{"replyTo":"2026-09-30","ccSelf":true,"attachPdf":true,"templates":{"invoice":{"subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached."}}},"logos":{"primaryName":"Karoo Fresh Holdings Ltd","primaryDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","primaryAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","associationName":"Karoo Fresh Holdings Ltd","associationDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","associationAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"defaults":{"bankDetails":"FNB Business Account 62012345678, branch 250655","footer":"Thank you for your business.","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year."},"autoRecon":{"enabled":true,"yoco":true,"payfast":true,"matchToleranceZar":1.0},"activeTemplateName":"Karoo Fresh Holdings Ltd"},"body":{"numbering":{"invoice":{"prefix":"INV-","next":1}},"labels":{"docTitle":{"invoice":"Tax Invoice"},"description":"Description","qty":"Qty","unitPrice":"Unit price","rate":"Rate","hours":"Hours","discount":"Discount","tax":"VAT","net":"Net","total":"Total"},"show":{"dueDate":true,"contactName":true,"businessAddress":true,"vatNumber":true,"discountColumn":true,"paymentLinks":true,"associationLogo":true},"email":{"replyTo":"2026-09-30","ccSelf":true,"attachPdf":true,"templates":{"invoice":{"subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached."}}},"logos":{"primaryName":"Karoo Fresh Holdings Ltd","primaryDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","primaryAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","associationName":"Karoo Fresh Holdings Ltd","associationDataUrl":"https://app.ledgrsa.com/pay/3f1a7c92","associationAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"defaults":{"bankDetails":"","footer":"","terms":"Payment within 30 days.","notes":""},"autoRecon":{"enabled":true,"yoco":false,"payfast":true,"matchToleranceZar":2.0},"activeTemplateName":"Site works"},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoice-settings/custom-fields","summary":"The active company's own document fields (at most ten), in order: a label, the document types it is offered on, and whether it prints on the customer's copy. Requires invoices:view.","auth":"jwt","responseExample":{"fields":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","docTypes":["standard"],"onCustomerCopy":true}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/invoice-settings/custom-fields","summary":"Replace the active company's own document fields. A field with a blank id is new; a known id keeps its values on documents; a field left out is no longer offered but still prints on documents that carry it. Refused by name: more than ten, a blank or duplicate name, a name over 40 characters, no document type. Requires invoices:edit.","auth":"jwt","body":{"fields":[{"id":"","label":"Site reference","docTypes":["invoice","quote"],"onCustomerCopy":true}]},"responseExample":{"fields":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","docTypes":["standard"],"onCustomerCopy":true}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/document-sequences","summary":"The prefix and next number for each of the nine document types.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docType":"invoice","prefix":"INV-","includeYear":true,"nextNumber":1,"padLength":1,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/document-sequences","summary":"Change a prefix or a starting number. A number already issued is never reissued.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docType":"invoice","prefix":"INV-","includeYear":true,"nextNumber":1,"padLength":1,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"docType":"invoice","prefix":"REF-0042","includeYear":true,"nextNumber":1001,"padLength":3},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/reminder-configs","summary":"The automated reminder schedule — how many days before and after due, and on which channel.","auth":"jwt","responseExample":{"enabled":true,"steps":[{"days":30,"email":true,"whatsapp":false}],"message":"Saved."},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/reminder-configs","summary":"Change the reminder schedule. Interest on overdue accounts is held to the National Credit Act's 2% a month (24% a year) unless interestDebtorsAreNotConsumers says none of the business's customers on credit is a consumer under the Act; it is stated to the customer as a monthly rate.","auth":"jwt","body":{"interestEnabled":false,"interestAnnualRatePercent":0.0,"interestDebtorsAreNotConsumers":false,"enabled":true,"steps":[{"days":3,"email":true,"whatsapp":true},{"days":7,"email":true,"whatsapp":false},{"days":14,"email":true,"whatsapp":false}],"message":""},"responseExample":{"enabled":true,"steps":[{"days":30,"email":true,"whatsapp":false}],"message":"Saved."},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/invoices/{id}/attachments","summary":"Files filed against a sales document — the customer's signed purchase order, a site drawing, a spec sheet. The bytes are not in the response: fetch each `attachmentId` through GET /api/files/{id}, which returns a signed URL as JSON.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"sequence":1,"uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","sendWithDocument":false}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/invoices/{id}/attachments?filename=SignedPO-4417.pdf&contentType=application/pdf&caption=Serial%20plate%20before%20fitting","summary":"Attach a file. RAW BYTES as the body, not multipart and not base64 — base64 inflates a 4 MB scan by a third on exactly the connection this product is designed for. Ten per document, 15 MB each, closed type list (see InvoiceAttachmentPolicy). Not sent to the customer unless “Send with the document” is ticked (PUT …/attachments/{attachmentId}).","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"sequence":1,"uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","sendWithDocument":false}],"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"PUT","path":"/api/invoices/{id}/attachments/{attachmentId}","summary":"Tick or untick “Send with the document”. Off by default: a ticked file goes on the email beside the document's PDF and is listed on the customer's portal page; an unticked one never leaves the business. Ticking a file that would take the ticked files past 10 MB — what one email can carry — is refused with 400 and a sentence. Returns the document's files.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"sequence":1,"uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","sendWithDocument":true}],"body":{"sendWithDocument":true},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/invoices/{id}/attachments/{attachmentId}","summary":"Unlink a file from the document. The stored object is NOT destroyed — an invoicing screen is not where evidence behind a disputed invoice should be shreddable.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"sequence":1,"uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","sendWithDocument":false}],"module":"invoices","plan":"Free","scope":"invoices:write"}]},{"name":"Payments & gateways","blurb":"PayFast is the one gateway that can take money, and its merchant credentials are per tenant. Resolution runs company, then tenant default, then deployment env — and that last step is skipped unless PAYFAST_ALLOW_DEPLOYMENT_MERCHANT declares a single-business deployment.","endpoints":[{"method":"GET","path":"/api/payment-gateways","summary":"Which gateways can actually take a payment on this deployment. The single source of truth both sides read — the client greys the rest out rather than offering a dead link.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","available":true,"reason":"Budget deferred to the next financial year."}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"GET","path":"/api/payment-gateways/payfast/credentials","summary":"The tenant's PayFast merchant details. The key is write-only and comes back only as a masked hint. Read is gated on invoices:view.","auth":"jwt","responseExample":{"configured":false,"source":"referral","merchantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","merchantKeyHint":"text","hasPassphrase":false,"sandbox":true,"active":true,"companyScoped":false,"updatedAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/payment-gateways/payfast/credentials","summary":"Store PayFast merchant credentials, encrypted with SecretBox. Gated on roles:edit, the administrator permission Settings → Payments is drawn on, because this decides which merchant account receives the money; a change of account is audited (masked, before and after) and emailed to the owner.","auth":"jwt","responseExample":{"configured":true,"source":"referral","merchantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","merchantKeyHint":"text","hasPassphrase":false,"sandbox":true,"active":true,"companyScoped":false,"updatedAt":"2026-09-01T09:15:00Z"},"body":{"merchantId":"10000100","merchantKey":"46f0cd694581a","passphrase":"jt7NOE43FZPn","sandbox":true,"active":true,"companyScoped":true},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/payment-gateways/payfast/credentials?companyScoped=true","summary":"Remove stored credentials. Payment links already minted stop resolving a merchant.","auth":"jwt","responseKind":"none","module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/payment-gateways/yoco/credentials","summary":"The tenant's Yoco account. The secret key is write-only and comes back only as a masked hint. Also returns the exact webhook URL to register in the Yoco portal, and what is still missing before a payment could be reported. Read is gated on invoices:view.","auth":"jwt","responseExample":{"configured":false,"source":"referral","secretKeyHint":"text","hasWebhookSecret":false,"live":false,"active":true,"companyScoped":false,"setupBlocker":"text","webhookUrl":"https://app.ledgrsa.com/pay/3f1a7c92","updatedAt":"2026-09-01T09:15:00Z"},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/payment-gateways/yoco/credentials","summary":"Store the tenant's Yoco secret key and webhook signing secret, encrypted with SecretBox. Gated on roles:edit, the administrator permission Settings → Payments is drawn on, because this decides which merchant account receives the money; a change of account is audited (masked, before and after) and emailed to the owner. Omitting webhookSecret leaves any stored one alone, because the two halves arrive separately: Yoco only reveals the signing secret once the webhook is registered, and registering it needs the URL this endpoint returns.","auth":"jwt","responseExample":{"configured":true,"source":"referral","secretKeyHint":"text","hasWebhookSecret":false,"live":false,"active":true,"companyScoped":false,"setupBlocker":"text","webhookUrl":"https://app.ledgrsa.com/pay/3f1a7c92","updatedAt":"2026-09-01T09:15:00Z"},"body":{"secretKey":"sk_test_abcdefghij1234567890","webhookSecret":"whsec_abcdefghij1234567890","active":true,"companyScoped":true},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/payment-gateways/yoco/credentials?companyScoped=true","summary":"Remove the stored Yoco account. Payment links already minted stop resolving an account.","auth":"jwt","responseKind":"none","module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/webhook-events","summary":"The payments inbox — incoming gateway events with their match state, matched, review or unmatched.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ts":"2026-09-01T09:15:00Z","gateway":"payfast","ref":"INV-0001","amount":10005.0,"currency":"ZAR","matched":"text","status":"sent","note":"Budget deferred to the next financial year."}],"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/webhook-events/{id}/match","summary":"Match an unmatched payment to an invoice by hand.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ts":"2026-09-01T09:15:00Z","gateway":"payfast","ref":"INV-0001","amount":10005.0,"currency":"ZAR","matched":"text","status":"sent","note":"Budget deferred to the next financial year."},"body":{"invoiceNumber":"INV-0001"},"module":"invoices","plan":"Free","scope":"invoices:write"}]},{"name":"Customer portal","blurb":"No JWT — a portal token scoped to one document, in the URL path. Renders with no JavaScript, because it has to survive any email client's browser handoff.","endpoints":[{"method":"GET","path":"/lead-form/{token}?sent=1","summary":"A business's hosted enquiry form, for a business with no website form of its own: name, company, email or phone, and a message. Each rendered form carries its own nonce. With sent=1 it thanks the visitor. An unknown or rotated link is 404.","auth":"none","responseKind":"html"},{"method":"POST","path":"/lead-form/{token}","summary":"A visitor sends the hosted enquiry form: one new, unassigned website lead on the form's company, answered with a 303 back to the thank-you page. The same form posted twice (its nonce) is one lead; a form with no email or phone is refused with 422 and writes nothing. Rate-limited per caller.","auth":"none","responseKind":"html"}]},{"name":"Sales CRM","blurb":"The six weeks before an invoice exists. Deal value is NET OF VAT, because output VAT is SARS' money and a VAT-inclusive pipeline overstates expected revenue by 15% against an income statement stated excluding it.","endpoints":[{"method":"GET","path":"/api/crm/leads?limit=50&page=1&status=new&ownerId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&source=referral&search=cape","summary":"Leads, paginated. The client reports \"50 of 312\" because a list that silently stops at fifty while looking complete is the failure paging was meant to fix.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"new","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","estimatedValue":10005.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","convertedContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","convertedAt":"2026-09-01T09:15:00Z","lostReason":"Budget deferred to the next financial year.","activityCount":3,"openTaskCount":3,"lastActivityAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/leads","summary":"Capture a lead.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"sent","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","estimatedValue":10005.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","convertedContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","convertedAt":"2026-09-01T09:15:00Z","lostReason":"Budget deferred to the next financial year.","activityCount":3,"openTaskCount":3,"lastActivityAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Sipho Dlamini","companyName":"Dlamini Logistics","email":"sipho@dlamini.example","phone":"+27821234567","source":"referral","status":"new","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","estimatedValue":85000.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/leads/{id}","summary":"One lead with its activities.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"sent","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","estimatedValue":10005.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","convertedContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","convertedAt":"2026-09-01T09:15:00Z","lostReason":"Budget deferred to the next financial year.","activityCount":3,"openTaskCount":3,"lastActivityAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"PUT","path":"/api/crm/leads/{id}","summary":"Update a lead or move its status through new, contacted, qualified, unqualified.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"sent","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","estimatedValue":10005.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","convertedContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","convertedAt":"2026-09-01T09:15:00Z","lostReason":"Budget deferred to the next financial year.","activityCount":3,"openTaskCount":3,"lastActivityAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"qualified","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","estimatedValue":92000.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","lostReason":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PATCH","path":"/api/crm/leads/{id}","summary":"Apply an edit made against a copy of the lead, merged with anything changed since: fields nobody else changed are written, a field changed elsewhere to a different value answers 409 with both values and writes nothing, and a replayed edit id is answered as done.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","source":"referral","status":"sent","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","estimatedValue":10005.0,"currency":"ZAR","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","convertedContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","convertedAt":"2026-09-01T09:15:00Z","lostReason":"Budget deferred to the next financial year.","activityCount":3,"openTaskCount":3,"lastActivityAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"editId":"9b2e4c61-7a3d-4f58-8e0c-1d6a5b3c2f47","base":{"email":"accounts@capeunion.example"},"changes":{"email":"finance@capeunion.example"},"baseUpdatedAt":"2026-09-01T09:15:00Z","conflicts":[]},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/leads/{id}","summary":"Delete a lead.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/leads/{id}/convert","summary":"Convert to a real contact, carrying the lead's activities across. Never duplicates a customer on the same email — the match runs through the same contactMatchKey the import uses.","auth":"jwt","responseExample":{"leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactCreated":true,"opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activitiesMoved":1},"body":{"contactType":"customer","createOpportunity":true,"opportunityName":"Karoo Fresh Holdings Ltd","opportunityValue":10005.0,"pipelineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","expectedCloseDate":"2026-09-01"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/leads/import?preview=true","summary":"Import leads from CSV. Set preview to run the same code and return the counts without writing. Deliberately forgiving: the only rejection is a row with no name, and money goes through parseFlexibleAmount because a pasted \"R1 500,50\" is what a South African spreadsheet contains.","auth":"jwt","contentType":"text/plain","bodyRaw":"name,business,email,phone,estimated value,source\nSipho Dlamini,Dlamini Logistics,sipho@dlamini.example,0821234567,85000,referral","notes":"The body is the CSV itself, as text/plain — not a JSON envelope. Add ?preview=true to count the rows without writing them; the preview and the commit read the same body through the same parser.","responseExample":{"created":1,"duplicates":1,"skipped":1,"errors":[],"detectedColumns":{"key":"text"},"previewOnly":false},"scope":"crm:write"},{"method":"GET","path":"/api/crm/pipeline?ownerId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&pipelineId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The kanban board — every open deal by stage, with count, total and weighted total per column.","auth":"jwt","responseExample":{"currency":"ZAR","columns":[{"stage":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"defaultProbability":15.0,"isWon":false,"isLost":false,"isActive":true},"count":3,"totalValue":10005.0,"weightedValue":10005.0,"opportunities":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":null},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}]}],"openCount":3,"openValue":10005.0,"weightedForecast":1.0,"overdueCount":3},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/opportunities?limit=50&page=1&pipelineId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&stageId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&status=open&ownerId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&campaignId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&search=cape","summary":"Deals as a table, soonest close date first. The answer is always one page of { items, total, page, limit, totalPages } (50 a page unless limit asks for another size, at most 200), the same paginated shape GET /api/crm/leads answers. Since API v2 this holds with neither page nor limit too; v1 answered every deal as one array. Every filter and the search run over every deal before a page is cut, and total counts them; pipelineId keeps one pipeline's deals. The board (GET /api/crm/pipeline) is the whole open pipeline.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"open","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/opportunities","summary":"Create a deal. A deal with no lines keeps its typed value, which is the normal early state rather than a fallback.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"pipelineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Warehouse expansion","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","value":26700.0,"currency":"ZAR","probability":15.0,"expectedCloseDate":"2026-10-31","source":"referral","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/opportunities/{id}","summary":"One deal, with its line count so a single-line deal is told apart from a priced one at the call site.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"PUT","path":"/api/crm/opportunities/{id}","summary":"Update a deal. Once it has lines, value is DERIVED — recomputeOpportunityValue is its only writer.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Warehouse expansion phase 2","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","value":10005.0,"currency":"ZAR","probability":15.0,"expectedCloseDate":"2026-11-30","source":"referral","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/opportunities/{id}","summary":"Delete a deal and its lines.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/opportunities/{id}/stage","summary":"Move a deal. Every move writes a history row, which is where cycle time comes from.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","probability":15.0,"lostReason":"Budget deferred to the next financial year.","note":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/opportunities/{id}/history","summary":"Every stage this deal has been through, and when.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromStageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromStageName":"Karoo Fresh Holdings Ltd","toStageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toStageName":"Karoo Fresh Holdings Ltd","fromProbability":15.0,"toProbability":15.0,"daysInPreviousStage":30,"changedByUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","changedByName":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","changedAt":"2026-09-01T09:15:00Z"}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/opportunities/{id}/lines","summary":"The deal's lines. They mirror invoice_lines field for field, so a line becomes an InvoiceLineRequest with no conversion step.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"PUT","path":"/api/crm/opportunities/{id}/lines","summary":"Replace the deal's lines and recompute its value in the same transaction. unit_cost is the one column invoice_lines does not have — snapshotted at pricing, nullable rather than zero, and it is what lets the board show margin on a deal that has not been invoiced.","auth":"jwt","body":[{"description":"Steel frame","quantity":40.0,"unitPrice":1850.0,"unitCost":1240.0,"vatRate":15.0}],"notes":"The body is a bare array of lines, replacing every line on the deal.","responseExample":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/opportunities/{id}/quote?documentType=invoice","summary":"Raise a real quote through the invoicing engine from the deal's own lines, and store the link both ways.","auth":"jwt","body":{"issueDate":"2026-08-22","validUntil":"2026-09-22"},"responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","documentType":"quote","lineCount":3,"total":10005.0,"currency":"ZAR"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/lead-form","summary":"The company's hosted enquiry form link (/lead-form/{token}), minted on first ask. A visitor's enquiry there becomes a new, unassigned website lead on this company. Null when the deployment has no public address.","auth":"jwt","responseExample":{"url":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/lead-form/rotate","summary":"A new hosted enquiry form link; the old one stops working at once, for the page and its post.","auth":"jwt","responseExample":{"url":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/emails","summary":"Send an email from one lead or one deal, from the business with Reply-To the salesperson, and record it once as an email activity on its timeline (and the contact's history). The address is the lead's or the deal contact's unless 'to' names one. A retry with the same clientId answers 200 with the activity already made and sends nothing; the activity's outcome says whether the mail service accepted it.","auth":"jwt","requestExample":{"leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subject":"Your quote","body":"Hi Thandi,\n\nThe quote we discussed is attached.","clientId":"9b2e4f61-0c3d-4a8e-b7f5-1d6c2a9e8f40"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"call","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","dueDate":"2026-09-01","completedAt":"2026-09-01T09:15:00Z","isOverdue":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadName":"Karoo Fresh Holdings Ltd","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","outcome":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/bcc-address","summary":"The company's BCC-to-CRM address: an email a salesperson sends from their own mail with this address in BCC lands on the lead (else the contact's open deal) it was written to, once per Message-ID. Null when the deployment receives no email.","auth":"jwt","responseExample":{"address":"12 Long Street, Cape Town, 8001"},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/pipelines","summary":"The tenant's sales pipelines, the default first, each with how many open deals stand in its stages.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"isDefault":false,"openDeals":1}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/pipelines","summary":"Add a sales pipeline; it gets the standard stages (Qualification to Closed won and Closed lost). A name already in use is refused with 409.","auth":"jwt","requestExample":{"name":"Wholesale"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"isDefault":false,"openDeals":1},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PUT","path":"/api/crm/pipelines/{id}","summary":"Rename a pipeline.","auth":"jwt","requestExample":{"name":"Wholesale and distribution"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"isDefault":false,"openDeals":1},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/pipelines/{id}","summary":"Delete a pipeline and its stages. Refused with 409 for the default pipeline, and for one that still holds deals — move them first.","auth":"jwt","responseKind":"none","module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/stages","summary":"The tenant's pipeline stages and their default probabilities.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"defaultProbability":15.0,"isWon":false,"isLost":false,"isActive":true}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/stages","summary":"Add a stage.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"defaultProbability":15.0,"isWon":false,"isLost":false,"isActive":true},"body":{"pipelineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Site survey","sortOrder":2,"defaultProbability":35,"isWon":true,"isLost":true,"isActive":true},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PUT","path":"/api/crm/stages/{id}","summary":"Rename, reorder or reprobability a stage.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sortOrder":1,"defaultProbability":15.0,"isWon":false,"isLost":false,"isActive":true},"body":{"name":"Karoo Fresh Holdings Ltd","sortOrder":1,"defaultProbability":15.0,"isWon":true,"isLost":true,"isActive":true},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/stages/{id}","summary":"Remove a stage. Refused while deals sit in it.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/activities?limit=50&page=1&ownerId=me&type=call&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&opportunityId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&leadId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&open=true&overdue=true","summary":"Calls, meetings, emails, notes and tasks, paginated. Linked polymorphically to a lead, a deal or a contact.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"call","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","dueDate":"2026-09-01","completedAt":"2026-09-01T09:15:00Z","isOverdue":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadName":"Karoo Fresh Holdings Ltd","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","outcome":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/activities","summary":"Log an activity or set a task. Logging one updates the contact's last_contacted_at, which is what makes \"nobody has called these fifteen customers in four months\" answerable.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"standard","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","dueDate":"2026-09-01","completedAt":"2026-09-01T09:15:00Z","isOverdue":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadName":"Karoo Fresh Holdings Ltd","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","outcome":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","body":"Your invoice INV-0001 is attached."},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"call","subject":"Follow up on the frame quote","body":"Your invoice INV-0001 is attached.","dueDate":"2026-08-28","completed":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"Interested — sending a quote on Friday"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PUT","path":"/api/crm/activities/{id}","summary":"Change an activity.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"standard","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","dueDate":"2026-09-01","completedAt":"2026-09-01T09:15:00Z","isOverdue":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadName":"Karoo Fresh Holdings Ltd","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","outcome":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"activityType":"standard","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","dueDate":"2026-08-29","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"Interested — sending a quote on Friday"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/activities/{id}","summary":"Delete an activity.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/activities/{id}/complete","summary":"Mark a task done.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","activityType":"standard","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","dueDate":"2026-09-01","completedAt":"2026-09-01T09:15:00Z","isOverdue":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadName":"Karoo Fresh Holdings Ltd","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","outcome":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/follow-ups?ownerId=me","summary":"My open tasks, oldest due first — the read the crm-tasks digest chases. No \"upcoming this week\": a digest listing work that is not yet due trains people to ignore it.","auth":"jwt","responseExample":[{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","lifecycleStage":"text","nextFollowUpDate":"2026-09-01","lastContactedAt":"2026-09-01T09:15:00Z","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","bucket":"text","daysOverdue":30,"daysSinceContact":30}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/owners","summary":"Who can own a lead, a deal or a task.","auth":"jwt","responseExample":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","role":"Accountant"}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/performance?from=2026-03-01&to=2027-02-28","summary":"Pipeline by stage, weighted forecast, win rate, average sales cycle, and per-owner and per-source breakdowns.","auth":"jwt","responseExample":{"currency":"ZAR","openCount":3,"openPipeline":1.0,"weightedForecast":1.0,"overdueCount":3,"wonCount":3,"wonValue":10005.0,"lostCount":3,"lostValue":10005.0,"winRatePct":1.0,"avgSalesCycleDays":1.0,"leadCount":3,"newLeadCount":3,"convertedLeadCount":3,"leadConversionRatePct":1.0,"openLeadCount":3,"openLeadValue":10005.0,"activityCount":3,"openTaskCount":3,"overdueTaskCount":3,"byStage":[{"stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","count":3,"totalValue":10005.0,"weightedValue":10005.0}],"byOwner":[{"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","openCount":3,"openValue":10005.0,"weightedValue":10005.0,"wonCount":3,"wonValue":10005.0,"lostCount":3,"winRatePct":1.0,"avgCycleDays":1.0,"activityCount":3}],"bySource":[{"source":"referral","leadCount":3,"opportunityCount":3,"wonCount":3,"wonValue":10005.0,"weightedValue":10005.0}],"targets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":10005.0,"currency":"ZAR","notes":"Budget deferred to the next financial year.","actualValue":10005.0,"attainmentPct":1.0,"remaining":1.0,"weightedForecast":1.0,"isCurrent":false}]},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"GET","path":"/api/crm/targets?from=2026-03-01&to=2027-02-28","summary":"Sales targets by period. owner_user_id null means the team's number. Attainment is NOT capped at 100, and no target renders as \"no target set\" rather than 0%.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":10005.0,"currency":"ZAR","notes":"Budget deferred to the next financial year.","actualValue":10005.0,"attainmentPct":1.0,"remaining":1.0,"weightedForecast":1.0,"isCurrent":false}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/targets","summary":"Set a target. Measured against won deal value net of VAT, attributed by closed_at — the period it was won in, not the one somebody hoped.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":10005.0,"currency":"ZAR","notes":"Budget deferred to the next financial year.","actualValue":10005.0,"attainmentPct":1.0,"remaining":1.0,"weightedForecast":1.0,"isCurrent":false},"body":{"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":250000.0,"currency":"ZAR","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PUT","path":"/api/crm/targets/{id}","summary":"Change a target.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":10005.0,"currency":"ZAR","notes":"Budget deferred to the next financial year.","actualValue":10005.0,"attainmentPct":1.0,"remaining":1.0,"weightedForecast":1.0,"isCurrent":false},"body":{"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","targetValue":300000.0,"currency":"ZAR","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/targets/{id}","summary":"Remove a target.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/campaigns","summary":"Campaigns with channel, window, budget against spend, and attributed leads, deals and won revenue.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","channel":"email","startDate":"2026-09-01","endDate":"2026-09-30","budget":1.0,"spend":1.0,"currency":"ZAR","status":"sent","targetAudience":"text","notes":"Budget deferred to the next financial year.","leadCount":3,"convertedLeadCount":3,"opportunityCount":3,"wonCount":3,"wonRevenue":1.0,"weightedPipeline":1.0,"roiPct":1.0,"costPerLead":10005.0,"conversionRatePct":1.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/campaigns","summary":"Create a campaign. Attribution is by the lead's source, so it is only as honest as the capture.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","channel":"email","startDate":"2026-09-01","endDate":"2026-09-30","budget":1.0,"spend":1.0,"currency":"ZAR","status":"sent","targetAudience":"text","notes":"Budget deferred to the next financial year.","leadCount":3,"convertedLeadCount":3,"opportunityCount":3,"wonCount":3,"wonRevenue":1.0,"weightedPipeline":1.0,"roiPct":1.0,"costPerLead":10005.0,"conversionRatePct":1.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Spring trade show","channel":"event","startDate":"2026-09-01","endDate":"2026-09-30","budget":40000.0,"spend":1.0,"currency":"ZAR","status":"sent","targetAudience":"Existing customers in Gauteng","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"PUT","path":"/api/crm/campaigns/{id}","summary":"Update a campaign or record spend against it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","channel":"email","startDate":"2026-09-01","endDate":"2026-09-30","budget":1.0,"spend":1.0,"currency":"ZAR","status":"sent","targetAudience":"text","notes":"Budget deferred to the next financial year.","leadCount":3,"convertedLeadCount":3,"opportunityCount":3,"wonCount":3,"wonRevenue":1.0,"weightedPipeline":1.0,"roiPct":1.0,"costPerLead":10005.0,"conversionRatePct":1.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Karoo Fresh Holdings Ltd","channel":"email","startDate":"2026-09-01","endDate":"2026-09-30","budget":1.0,"spend":38200.0,"currency":"ZAR","status":"sent","targetAudience":"Existing customers in Gauteng","notes":"Budget deferred to the next financial year."},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/campaigns/{id}","summary":"Delete a campaign.","auth":"jwt","responseExample":{"status":"deleted"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/attachments?opportunityId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&leadId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Files linked to a deal, a lead or a contact. A link table rather than a column, because a deal has several and a single column means the second upload silently replaces the first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","createdAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena"}],"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"POST","path":"/api/crm/attachments/upload","summary":"Store a file and return its id. Raw bytes with the content type in the header, never base64 — a picker hands the client a ByteArray on every target and base64 inflates a 4MB drawing by a third. The server decides the stored content type from a closed list, never the one the client claims. The id then goes to POST /api/crm/attachments, which is what decides where it may be attached.","auth":"jwt","responseExample":{"attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contentType":"application/pdf","sizeBytes":1},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"POST","path":"/api/crm/attachments","summary":"Link an attachment to a deal, a lead or a contact.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","createdAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena"},"body":{"attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Signed acceptance","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","opportunityId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"DELETE","path":"/api/crm/attachments/{id}","summary":"Unlink. Removes the LINK, not the file — the same attachment may be referenced elsewhere, and a CRM screen is not where somebody should be able to destroy a receipt.","auth":"jwt","responseExample":{"status":"unlinked"},"module":"crm","plan":"Starter","scope":"crm:write"},{"method":"GET","path":"/api/crm/contacts/{id}/summary","summary":"The CRM panel inside the contact detail view — open deals, recent activities and lifecycle stage. One contact record, two views onto it.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lifecycleStage":"text","industry":"text","website":"https://app.ledgrsa.com/pay/3f1a7c92","nextFollowUpDate":"2026-09-01","lastContactedAt":"2026-09-01T09:15:00Z","ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","openOpportunityCount":3,"openOpportunityValue":10005.0,"weightedValue":10005.0,"wonCount":3,"wonValue":10005.0,"openTaskCount":3,"overdueTaskCount":3,"isStale":false,"opportunities":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stageName":"Karoo Fresh Holdings Ltd","stageIsWon":false,"stageIsLost":false,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownerName":"Thandi Mokoena","value":10005.0,"currency":"ZAR","probability":15.0,"weightedValue":10005.0,"expectedCloseDate":"2026-09-01","source":"referral","status":"sent","lostReason":"Budget deferred to the next financial year.","closedAt":"2026-09-01T09:15:00Z","campaignId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","campaignName":"Karoo Fresh Holdings Ltd","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","kind":"PRODUCT","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productCode":"CT-001","quantity":3.0,"unitPrice":2900.0,"unitCost":2900.0,"discountRate":0.0,"discountFixed":0.0,"discountType":"PERCENT","vatRate":15.0,"vatInclusive":false,"notes":"Budget deferred to the next financial year.","lineSubtotal":8700.0,"discountAmount":0.0,"vatAmount":1305.0,"lineTotal":10005.0}],"lineCount":3,"totals":{"currency":"ZAR","subtotal":8700.0,"discountTotal":0.0,"vatTotal":1305.0,"netValue":8700.0,"grossValue":10005.0,"lineCount":3,"margin":{"revenue":1.0,"cost":10005.0,"profit":1.0,"marginPct":1.0,"costKnownForAllLines":true}},"decision":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","status":"sent","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","declineReason":"Budget deferred to the next financial year.","awaitingDecision":false},"ageDays":30,"activityCount":3,"openTaskCount":3,"nextActivityDue":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}]},"module":"crm","plan":"Starter","scope":"crm:read"},{"method":"PUT","path":"/api/crm/contacts/{id}","summary":"Set the CRM enrichment — lifecycle stage, industry, website and next follow-up.","auth":"jwt","body":{"lifecycleStage":"customer","industry":"Logistics","website":"https://dlamini.example"},"responseKind":"json","module":"crm","plan":"Starter","scope":"crm:write"}]},{"name":"Customer ordering portal API","blurb":"The mirror of the supplier portal, on the sales side. A customer holds a token scoped to one contacts row, sent to this API as a bearer header (the customer's own pages, below, carry it in the path). They browse the products the business has flagged sellable, at its standard price, and submit a basket. That basket becomes a DRAFT quote: it reserves no stock, posts nothing and binds no price until a person on the sales side reviews it and sends it, which is the exact mirror of the rule that a supplier cannot create a liability. Prices are never accepted from the client — the server prices the basket from products.sell_price at the moment of submission.","endpoints":[{"method":"GET","path":"/customer-api/v1/session","summary":"Who the token belongs to, which business they are buying from, and what is waiting.","auth":"customer-token","responseExample":{"customerName":"Acme Trading","sellerName":"Dlamini Supplies","productCount":240,"quotesAwaitingResponse":1,"quotesReadyToReview":2,"openInvoices":3,"amountOutstanding":18450.0,"currency":"ZAR","accessExpiresAt":"2027-09-11T08:14:00Z"}},{"method":"GET","path":"/customer-api/v1/products","summary":"The price book: products flagged is_sellable, at the standard sell price. Carries no cost price and no stock quantity — only an in-stock indicator, and null on an item that is not stock-tracked.","auth":"customer-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"BOLT-M8-50","name":"M8 x 50mm hex bolt","category":"fasteners","unit":"each","unitPrice":4.5,"vatRate":15.0,"inStock":true,"qtyPrecision":0}]},{"method":"POST","path":"/customer-api/v1/basket","summary":"Submit a basket. Produces a DRAFT quote priced from the seller's own price book, in its own currency and at the VAT the seller actually charges — it commits the business to nothing until a person reviews and sends it. Send a clientReference to make a retry safe: the same value answers the quote the first request made.","auth":"customer-token","body":{"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":20}],"reference":"PO-4471","note":"Needed before Friday.","contactName":"Thandi Mokoena","clientReference":"po-4471-try-1"},"responseExample":{"ok":true,"message":"Thank you — Dlamini Supplies has your request and will come back to you with a quote.","quote":{"number":"QTE-2026-118","status":"draft","total":103.5,"currency":"ZAR","submittedByCustomer":false,"awaitingSeller":false}}},{"method":"GET","path":"/customer-api/v1/quotes","summary":"Their quotes — the ones they submitted and the ones the seller has sent back. A draft the SELLER is still working on is deliberately not listed.","auth":"customer-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"QTE-2026-118","status":"draft","issueDate":"2026-09-11","total":103.5,"currency":"ZAR","submittedByCustomer":false,"awaitingSeller":false}]},{"method":"GET","path":"/customer-api/v1/quotes/{id}","summary":"One quote with its lines. 404 when it is not on this customer's account.","auth":"customer-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"QTE-2026-118","status":"draft","subtotal":90.0,"vatTotal":13.5,"total":103.5,"currency":"ZAR","submittedByCustomer":false,"awaitingSeller":false,"lines":[{"description":"M8 x 50mm hex bolt","sku":"BOLT-M8-50","quantity":20.0,"unitPrice":4.5,"vatRate":15.0,"lineTotal":103.5}]}}]},{"name":"Expenses & claims","blurb":"Expenses, supplier bills, mileage, per diem and petty cash. Mileage is at the SARS s8(1)(b)(iii) rate resolved from the TRIP's date, so a prior-year trip logged late is paid at that year's rate.","endpoints":[{"method":"GET","path":"/api/expenses?status=submitted,approved&category=fuel&q=engen&from=2026-09-01&to=2026-09-30&jobCardId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&limit=50&offset=0","summary":"Expense entries, newest first. Filtered in SQL: status (comma-separated, any case), category (uncategorised matches none set), q (supplier, description or note), from/to (the expense date, inclusive) and jobCardId (an id, or none). With no limit it is the whole list; limit (at most 500) and offset page it, and GET /api/expenses/count gives the total for the same filters.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/count?status=submitted,approved&category=fuel&q=engen&from=2026-09-01&to=2026-09-30&jobCardId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"How many expenses GET /api/expenses would page through for the same filters, so a list can say how many of how many it shows.","auth":"jwt","responseExample":{"total":10000},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/summary","summary":"The Expenses screen's figures over every expense of the active company: how many there are, wait on an approver, are drafts and still owe a receipt, gross spend (amount + VAT) by month, category and status over the six months to asOf, and every category in use. Which statuses count as spend is the reader's rule: approved and paid claims.","auth":"jwt","responseExample":{"asOf":"2026-10-03","count":10000,"awaitingDecision":42,"drafts":17,"missingReceipts":63,"spend":[{"month":"2026-10","category":"fuel","status":"APPROVED","gross":1150.0}],"categories":["fuel","meals","travel"]},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/category-memory","summary":"What Ledgr has learned about filing each supplier — the category the capture screen suggests next time, learned from how documents were actually filed, with the same sentence that screen shows. This company's memories plus the holding company's.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","category":"consumables","timesSeen":3,"lastUsedAt":"2026-09-01T08:00:00Z","sentence":"Karoo Fresh Holdings Ltd was filed to consumables the last 3 times."}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"DELETE","path":"/api/expenses/category-memory/{id}","summary":"Forget one learned supplier, so it is no longer suggested. The next document filed from that supplier starts a new memory.","auth":"jwt","responseExample":{"status":"forgotten"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses","summary":"Capture an expense. Accepts a client-minted id, which is what makes offline replay idempotent — the id becomes the row's primary key. A purchase of goods received by hand can name productId and productQty: it is booked to Purchases and clears those goods from 2115 Goods Received Not Invoiced, and a price difference follows the stock.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productQty":2.0,"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001"},"body":{"vatUse":"taxable","vatType":"standard","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","inboxItemId":"7c2e9b14-0a35-4f6d-8e21-5b9d3c4a1f08","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"vatRate":15.0,"currency":"ZAR","exchangeRate":1.0,"vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productQty":2.0,"jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rechargeable":false,"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/{id}","summary":"One expense with its receipt and approval trail.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/expenses/{id}","summary":"Update an expense.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001"},"body":{"vatUse":"taxable","vatType":"standard","date":"2026-09-01","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"description":"Consulting services — August 2026","amount":10005.0,"vatRate":15.0,"vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productQty":2.0,"receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rechargeable":true,"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/expenses/{id}","summary":"Delete an expense.","auth":"jwt","responseExample":{"ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/{id}/submit","summary":"Submit for approval.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/{id}/approve","summary":"Approve. This is a write transaction that runs a full GL posting, so it goes through dbQuery rather than on the request thread.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/{id}/reject","summary":"Reject, with a reason.","auth":"jwt","body":{"reason":"No VAT invoice attached"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/{id}/pay","summary":"Record the reimbursement. Posts the payment as its own entry (DR 2120 / CR the account named by bankAccountId) on `date` - the day the money left; today when absent, never before the claim, never after today - beside the approval accrual that stays in the claim's own month, so a claim from a closed month can be paid in an open one.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/receipts","summary":"Upload a receipt image. The bytes go to object storage; the row holds the reference.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","base64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/receipts/{id}","summary":"The legacy base64 receipt read path, kept until the attachment backfill finishes. New code should use GET /api/files/{id}.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","base64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/expenses/ocr","summary":"Run Tesseract over a receipt and return the legacy field shape.","auth":"jwt","responseKind":"json","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/categories","summary":"The categories expenses and bills are filed against. Needs expenses:view and the Expenses module, not Inventory.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"fuel-and-tolls","name":"Fuel and tolls","color":"#0D47A1","icon":"fuel","sortOrder":0,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","productCount":0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/category-bookings","summary":"Where a document filed under each category word books: the tenant's categories, the built-ins and the words its expenses and bills already carry. booksToFallback is true where nothing maps the word and it lands in 6340 Sundry Expenses. Needs expenses:view and the Expenses module.","auth":"jwt","responseExample":[{"category":"repairs","accountCode":"6180","accountName":"Repairs & Maintenance","booksToFallback":false}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/expenses/categories","summary":"Add an expense category. The code is derived from the name when left blank. Needs expenses:create and the Expenses module, not Inventory.","auth":"jwt","body":{"code":"","name":"Fuel and tolls","color":"#0D47A1","description":"Fuel, e-tolls and parking for business trips","icon":"fuel","sortOrder":0,"accountCode":"6190"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"fuel-and-tolls","name":"Fuel and tolls","color":"#0D47A1","icon":"fuel","sortOrder":0,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","productCount":0},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"PUT","path":"/api/expenses/categories/{id}","summary":"Edit an expense category, above all the expense account it books to (a blank accountCode clears it). The same edit as PUT /api/inventory/categories/{id}, under the Expenses module: needs expenses:edit, not Inventory.","auth":"jwt","body":{"code":"fuel-and-tolls","name":"Fuel and tolls","color":"#0D47A1","icon":"fuel","description":"Fuel, e-tolls and parking for business trips","sortOrder":0,"isActive":true,"accountCode":"6190"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"fuel-and-tolls","name":"Fuel and tolls","color":"#0D47A1","icon":"fuel","sortOrder":0,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","productCount":0},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/category-budgets","summary":"Budget against actual per expense category.","auth":"jwt","responseExample":[{"category":"Office supplies","monthlyBudget":1.0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/expenses/category-budgets/{category}","summary":"Set a category's monthly budget.","auth":"jwt","body":{"monthlyBudget":15000.0},"responseExample":{"category":"Office supplies","monthlyBudget":1.0},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/documents/ocr?expenseId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&billId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Documents already scanned, with per-field confidence, provenance and raw text.","auth":"jwt","responseExample":{"ok":true,"engine":"text","documentKind":"invoice","extraction":{"supplierName":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","documentNumber":"INV-0001","documentDate":"2026-09-01","subtotal":8700.0,"vatAmount":1305.0,"vatRatePercent":15.0,"total":10005.0,"currency":"ZAR","categoryHint":"text","litres":1.0,"lineItems":[{"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"amount":10005.0,"confidence":1}],"fields":[{"name":"Karoo Fresh Holdings Ltd","confidence":1,"source":"referral","evidence":"text"}],"reconciliation":{"subtotalPlusVatMatchesTotal":true,"impliedVatRatePercent":15.0,"vatRateRecognised":true,"discrepancy":1.0,"lineItemsSum":1.0,"lineItemsMatchSubtotal":true},"overallConfidence":1,"engineConfidence":1,"engineScored":false,"warnings":[],"droppedLowConfidence":["text"],"manualEntryRequired":true},"rawText":"text","ocrResultId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","failure":"text","error":"text","manualEntryRequired":false,"variant":"text","passes":1,"pageCount":1,"pagesRead":1,"truncated":false,"exactText":false,"duplicateOf":{"ocrResultId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","scannedAt":"2026-09-01T09:15:00Z","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","message":"Saved."},"suggestion":{"category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Budget deferred to the next financial year."}},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/documents/ocr?kind=receipt&currency=ZAR","summary":"Scan a receipt, supplier invoice or statement — PDF, JPEG, PNG or multi-page TIFF. Unlike /api/expenses/ocr this returns confidence and provenance per field, not just values.","auth":"jwt","responseExample":{"ok":true,"engine":"text","documentKind":"invoice","extraction":{"supplierName":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","documentNumber":"INV-0001","documentDate":"2026-09-01","subtotal":8700.0,"vatAmount":1305.0,"vatRatePercent":15.0,"total":10005.0,"currency":"ZAR","categoryHint":"text","litres":1.0,"lineItems":[{"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"amount":10005.0,"confidence":1}],"fields":[{"name":"Karoo Fresh Holdings Ltd","confidence":1,"source":"referral","evidence":"text"}],"reconciliation":{"subtotalPlusVatMatchesTotal":true,"impliedVatRatePercent":15.0,"vatRateRecognised":true,"discrepancy":1.0,"lineItemsSum":1.0,"lineItemsMatchSubtotal":true},"overallConfidence":1,"engineConfidence":1,"engineScored":false,"warnings":[],"droppedLowConfidence":["text"],"manualEntryRequired":true},"rawText":"text","ocrResultId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","failure":"text","error":"text","manualEntryRequired":false,"variant":"text","passes":1,"pageCount":1,"pagesRead":1,"truncated":false,"exactText":false,"duplicateOf":{"ocrResultId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","scannedAt":"2026-09-01T09:15:00Z","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","message":"Saved."},"suggestion":{"category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Budget deferred to the next financial year."}},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/documents/inbox?status=open&offset=0","summary":"The document inbox: everything uploaded in bulk or emailed in, newest first, with what the reader made of each.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"referral","status":"sent","documentKind":"standard","fileName":"SignedPO-4417.pdf","contentType":"application/pdf","sizeBytes":1,"pageCount":3,"supplierName":"Karoo Fresh Holdings Ltd","documentDate":"2026-09-01","totalAmount":10005.0,"currency":"ZAR","confidence":1,"exactText":false,"fromEmail":"accounts@karoofresh.example","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","receivedAt":"2026-09-01T09:15:00Z","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateOfId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateNote":"Budget deferred to the next financial year.","error":"text","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","splitFromId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","splitIndex":1,"splitCount":3,"splitNote":"Budget deferred to the next financial year.","statementAccountRef":"INV-0001","statementStart":"2026-09-01","statementEnd":"2026-09-30","statementTransactionCount":3,"statementImported":1,"statementDuplicates":1,"statementBalances":true,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","statementNote":"Budget deferred to the next financial year."}],"total":42,"limit":50,"offset":0,"counts":{"key":3}},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/documents/inbox?kind=receipt","summary":"Drop documents in. Multipart, several files at a time; answers immediately and reads them off the request.","auth":"jwt","responseExample":{"accepted":1,"rejected":0,"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"referral","status":"sent","documentKind":"standard","fileName":"SignedPO-4417.pdf","contentType":"application/pdf","sizeBytes":1,"pageCount":3,"supplierName":"Karoo Fresh Holdings Ltd","documentDate":"2026-09-01","totalAmount":10005.0,"currency":"ZAR","confidence":1,"exactText":false,"fromEmail":"accounts@karoofresh.example","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","receivedAt":"2026-09-01T09:15:00Z","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateOfId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateNote":"Budget deferred to the next financial year.","error":"text","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","splitFromId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","splitIndex":1,"splitCount":3,"splitNote":"Budget deferred to the next financial year.","statementAccountRef":"INV-0001","statementStart":"2026-09-01","statementEnd":"2026-09-30","statementTransactionCount":3,"statementImported":1,"statementDuplicates":1,"statementBalances":true,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","statementNote":"Budget deferred to the next financial year."}],"errors":[]},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/documents/inbox/{id}","summary":"One item's full reading, plus what this tenant's own history says to file it as.","auth":"jwt","responseExample":{"item":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"referral","status":"sent","documentKind":"standard","fileName":"SignedPO-4417.pdf","contentType":"application/pdf","sizeBytes":1,"pageCount":3,"supplierName":"Karoo Fresh Holdings Ltd","documentDate":"2026-09-01","totalAmount":10005.0,"currency":"ZAR","confidence":1,"exactText":false,"fromEmail":"accounts@karoofresh.example","subject":"Invoice INV-0001 from Karoo Fresh Holdings Ltd","receivedAt":"2026-09-01T09:15:00Z","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateOfId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","duplicateNote":"Budget deferred to the next financial year.","error":"text","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","splitFromId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","splitIndex":1,"splitCount":3,"splitNote":"Budget deferred to the next financial year.","statementAccountRef":"INV-0001","statementStart":"2026-09-01","statementEnd":"2026-09-30","statementTransactionCount":3,"statementImported":1,"statementDuplicates":1,"statementBalances":true,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","statementNote":"Budget deferred to the next financial year."},"extraction":{"supplierName":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","documentNumber":"INV-0001","documentDate":"2026-09-01","subtotal":8700.0,"vatAmount":1305.0,"vatRatePercent":15.0,"total":10005.0,"currency":"ZAR","categoryHint":"text","litres":1.0,"lineItems":[{"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"amount":10005.0,"confidence":1}],"fields":[{"name":"Karoo Fresh Holdings Ltd","confidence":1,"source":"referral","evidence":"text"}],"reconciliation":{"subtotalPlusVatMatchesTotal":true,"impliedVatRatePercent":15.0,"vatRateRecognised":true,"discrepancy":1.0,"lineItemsSum":1.0,"lineItemsMatchSubtotal":true},"overallConfidence":1,"engineConfidence":1,"engineScored":false,"warnings":[],"droppedLowConfidence":["text"],"manualEntryRequired":true},"rawText":"text","suggestion":{"category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Budget deferred to the next financial year."},"bankAccounts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumberHint":"62012345678","currency":"ZAR","matchesStatement":false}]},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/documents/inbox/{id}/thumbnail","summary":"A small JPEG of the document — a photograph shrunk, or a PDF's first page — for the Inbox row. 404 when there is nothing that can be drawn.","auth":"jwt","responseKind":"binary","module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/documents/inbox/{id}/retry","summary":"Put a failed item back in the reading queue.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/documents/inbox/{id}/unsplit","summary":"Put a page that was split into several documents back together: the crops are discarded and the whole page is read again as one.","auth":"jwt","responseExample":{"ok":true,"discarded":1},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/documents/inbox/{id}/discard","summary":"Throw an inbox item away without filing it.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/documents/inbox/{id}/import-statement","summary":"Import an emailed bank statement into the account you choose. Held statements are the ones that read perfectly but could not prove which account they belong to, or did not add up to the closing balance the bank printed. Gated on banking:create, not expenses — this writes bank transactions.","auth":"jwt","responseExample":{"imported":1,"duplicates":1,"total":2,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","message":"Saved."},"body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","confirmDifferentAccount":false,"saveAccountNumber":false,"confirmRowDoubts":false},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/documents/inbox/{id}/link","summary":"Attach an inbox item to the expense or bill it became, and remember how this supplier gets filed.","auth":"jwt","responseKind":"none","body":{"expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"fuel","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/documents/inbox/address","summary":"This company's email-in address. Minted on first ask; absent when the deployment cannot receive email.","auth":"jwt","responseExample":{"configured":false,"address":"12 Long Street, Cape Town, 8001","note":"Budget deferred to the next financial year."},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/documents/inbox/address/rotate","summary":"Issue a new email-in address. The previous one stops working immediately.","auth":"jwt","responseExample":{"configured":false,"address":"12 Long Street, Cape Town, 8001","note":"Budget deferred to the next financial year."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/documents/ocr/{id}/link","summary":"Attach a scan to the expense or bill it turned into.","auth":"jwt","responseKind":"none","body":{"expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills?status=due&jobCardId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&submitted=true&approval=awaiting","summary":"Supplier invoices.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/bills","summary":"Capture a supplier invoice.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"body":{"approve":null,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","inboxItemId":"7c2e9b14-0a35-4f6d-8e21-5b9d3c4a1f08","vendor":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatRate":15.0,"currency":"ZAR","exchangeRate":1.0,"billNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":null,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"category":"Office supplies","recurring":false,"frequency":"monthly","endDate":"2026-09-30","reference":"INV-0001","notes":"Budget deferred to the next financial year.","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rentedLeaseId":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/{id}","summary":"One bill with its lines and payments.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/bills/{id}","summary":"Update a bill.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"body":{"exchangeRate":18.5,"vendor":"Karoo Fresh Holdings Ltd","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":null,"billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatRate":15.0,"currency":"ZAR","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","status":"sent","recurring":true,"frequency":"monthly","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rentedLeaseId":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}]},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/bills/{id}","summary":"Delete a bill.","auth":"jwt","responseExample":{"ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/{id}/pay","summary":"Record a payment against a bill. Send date (yyyy-MM-dd) for the day the money left - not before the bill, not after today, and not inside a filed VAT201 period on the payments basis, where the input tax is claimed in the month it is paid. A foreign bill settles at the exchangeRate sent, else at the rate on file for the day it is paid, and the difference from the rate it was booked at is booked as an exchange gain or loss (IFRS for SMEs 30.10); with no rate on file it settles at the bill's own.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","customsReference":null,"openMarketValue":null}],"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"body":{"date":"2026-09-25","exchangeRate":18.5,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/{id}/payments","summary":"Pay part of a bill, or set a supplier prepayment against it. An instalment is money out of bankAccountId (or the pooled bank) on date, never before the bill's own date and never after today, and posts its own journal at that date: the bill owes what is left. A foreign bill's instalment settles at exchangeRate, else at the rate on file for date, and books the exchange difference. The instalment that leaves nothing owing settles the bill. With prepaymentId, that prepayment is set against the bill (amount absent takes as much as the bill still owes) and no money moves. Refused for more than is still owed, an unapproved bill and one a three-way-match exception holds.","auth":"jwt","body":{"amount":400.0,"date":"2026-09-20","bankAccountId":"8d2e4b17-6c3a-4f90-b5e1-7a9c0d3f2b64","exchangeRate":null,"reference":"EFT 4471","prepaymentId":null},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amountPaid":0.0,"amountDue":10005.0,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","kind":"standard","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vatType":"standard","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customsReference":null,"openMarketValue":null}],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","paymentHold":"text","exchangeRate":1.0,"paymentFxRate":15.0,"baseGross":1.0,"approvalStatus":"approved","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","approvalProgress":{"given":1,"needed":1,"approverNames":["Thandi Mokoena"],"youApproved":false},"documentUrl":"https://app.ledgrsa.com/pay/3f1a7c92","documentVatUnclaimed":1305.0,"vatNotices":[{"code":"CT-001","message":"Saved.","redateTo":"2026-09-30"}],"inputVatNotClaimed":1305.0,"sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/{id}/payments","summary":"What has been paid on a bill: each instalment, prepayment set against it and part contra, oldest first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"currency":"ZAR","method":"eft","reference":"INV-0001","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","remaining":1.0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"DELETE","path":"/api/bills/{id}/payments/{paymentId}","summary":"Take an instalment or an allocated prepayment back off a bill that is not yet paid. The instalment's journal is reversed; a prepayment is free to be set against another bill. Refused on a paid bill (mark it unpaid first) and for a part contra.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amountPaid":0.0,"amountDue":10005.0,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","kind":"standard","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vatType":"standard","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customsReference":null,"openMarketValue":null}],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","paymentHold":"text","exchangeRate":1.0,"paymentFxRate":15.0,"baseGross":1.0,"approvalStatus":"approved","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","approvalProgress":{"given":1,"needed":1,"approverNames":["Thandi Mokoena"],"youApproved":false},"documentUrl":"https://app.ledgrsa.com/pay/3f1a7c92","documentVatUnclaimed":1305.0,"vatNotices":[{"code":"CT-001","message":"Saved.","redateTo":"2026-09-30"}],"inputVatNotClaimed":1305.0,"sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/suppliers/{id}/prepayments","summary":"Money paid to a supplier before their bill. It sits as a debit balance on the supplier in trade payables, shows as a negative line on their statement and in aged creditors, and is set against a bill later with POST /api/bills/{id}/payments and its prepaymentId. In the company's own currency.","auth":"jwt","body":{"amount":300.0,"date":"2026-09-10","bankAccountId":"8d2e4b17-6c3a-4f90-b5e1-7a9c0d3f2b64","reference":"Advance on order"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"currency":"ZAR","method":"eft","reference":"INV-0001","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","remaining":1.0},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/suppliers/{id}/prepayments","summary":"A supplier's prepayments, oldest first, each with what is not yet set against a bill. Paged: limit (default 200, at most 500) and offset.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","amount":10005.0,"currency":"ZAR","method":"eft","reference":"INV-0001","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","remaining":1.0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"DELETE","path":"/api/suppliers/{id}/prepayments/{paymentId}","summary":"Withdraw a prepayment no bill has taken. Its journal is reversed. Refused once any of it is set against a bill.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/mileage/trips","summary":"Logged trips with their calculated claim.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/mileage/trips","summary":"Log a trip. The rate is year-keyed on SarsTravelRates and resolved from the trip's own date — R4.95/km for 2026/27, R4.76/km for 2025/26.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-30","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":145.0,"ratePerKm":1.0,"purpose":"Site inspection","vehicle":"CA 123-456","notes":"Budget deferred to the next financial year.","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"PUT","path":"/api/mileage/trips/{id}","summary":"Correct a trip.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":64.0,"ratePerKm":1.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","notes":"Budget deferred to the next financial year.","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clearContactId":false,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/mileage/trips/{id}","summary":"Delete a trip.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/per-diem/claims","summary":"Travel allowance claims.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/per-diem/claims","summary":"Raise a per diem claim.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","fromDate":"2026-09-01","toDate":"2026-09-30","tripKind":"overnight","days":30,"rateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ratePerDay":15.0,"notes":"Budget deferred to the next financial year.","country":"United Kingdom","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"PUT","path":"/api/per-diem/claims/{id}","summary":"Update a claim.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"rateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","fromDate":"2026-09-01","toDate":"2026-09-03","tripKind":"overnight","days":3,"ratePerDay":1.0,"status":"sent","notes":"Budget deferred to the next financial year.","country":"United Kingdom","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/per-diem/claims/{id}","summary":"Delete a claim.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/per-diem/claims/{id}/approve","summary":"Approve a claim.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/per-diem/claims/{id}/reject","summary":"Reject a claim, with a reason.","auth":"jwt","body":{"reason":"Dates overlap an existing claim"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/per-diem/claims/{id}/pay","summary":"Record payment of a claim, on `date` (the day the money left; today when absent, never before the claim, never after today) as its own entry beside the approval accrual.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employee":"Thandi Mokoena","destination":"accounts@karoofresh.example","periodLabel":"2026-09","days":30,"ratePerDay":1.0,"totalAmount":10005.0,"policy":"fifo","status":"sent","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/per-diem/rates","summary":"The company's own per-diem rates — the only rates a claim may be raised at.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","dailyAmount":10005.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/per-diem/rates","summary":"Add a per-diem rate (expenses:approve).","auth":"jwt","body":{"name":"Overnight, local","dailyAmount":650.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","dailyAmount":10005.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"PUT","path":"/api/per-diem/rates/{id}","summary":"Change a per-diem rate. Claims already raised keep the rate they were raised at.","auth":"jwt","body":{"name":"Overnight, local","dailyAmount":700.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","dailyAmount":10005.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/per-diem/rates/{id}","summary":"Remove a per-diem rate. Claims already raised keep the rate they were raised at.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/petty-cash","summary":"The float and its transactions.","auth":"jwt","responseExample":{"floatAmount":10005.0,"balance":10005.0,"txns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"category":"Office supplies","receipt":false,"createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}]},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/petty-cash/float","summary":"Set the float: the tin is topped back up to it, drawing (or paying back) the difference from the bank.","auth":"jwt","body":{"floatAmount":1500.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankTransactionId":null,"date":"2026-09-01"},"responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/petty-cash/counts","summary":"Count the tin: the cash found against the books. The difference is booked to Sundry Expenses and the tin holds what was counted.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","countedAmount":720.0,"bookAmount":730.0,"difference":-10.0,"note":"Month-end count","createdAt":"2026-09-01T09:15:00Z"},"body":{"countedAmount":720.0,"date":"2026-09-01","note":"Month-end count"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/petty-cash/counts","summary":"The counts of the tin, newest first and 100 at a time (`?limit=` up to 500, `?offset=` for older ones): the cash counted, what the books held, and the difference.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","countedAmount":720.0,"bookAmount":730.0,"difference":-10.0,"note":"Month-end count","createdAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/petty-cash/txns","summary":"Record a petty-cash payment or receipt.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"category":"Office supplies","receipt":false,"createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"vatAmount":13.04,"supplierVatNumber":"4210102051","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-08-19","description":"Courier","amount":145.0,"category":"Postage","receipt":false,"notes":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"PUT","path":"/api/petty-cash/txns/{id}","summary":"Correct a petty-cash transaction.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"category":"Office supplies","receipt":false,"createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"vatAmount":13.04,"supplierVatNumber":"4210102051","date":"2026-09-01","description":"Consulting services — August 2026","amount":150.0,"category":"Office supplies","receipt":true,"notes":"Budget deferred to the next financial year.","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/petty-cash/txns/{id}","summary":"Delete a petty-cash transaction.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/expenses/{id}/reopen","summary":"Un-pay a claim: PAID back to APPROVED, reversing the cash leg to the accrual. Needs expenses:approve, because it undoes a payment decision. Added with the settlement guard and required by it — refusing to edit a paid claim would otherwise be a dead end, as this module had no way back from PAID at all.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","supplierVatNumber":"4123456789","category":"Office supplies","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","status":"sent","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","notes":"Budget deferred to the next financial year.","rejectionReason":"Budget deferred to the next financial year.","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","rechargeable":false,"rechargeInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/mileage/trips/{id}/submit","summary":"Submit a logged trip for approval. The claimant's own act, so expenses:create rather than approve.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/mileage/trips/{id}/approve","summary":"Approve a trip. Posts DR 6280 Mileage Reimbursement / CR 2120 Accruals at the cent-rounded claim. Needs expenses:approve — before these endpoints existed the only way to write a status was PUT, which took any string on expenses:edit.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/mileage/trips/{id}/reject","summary":"Reject a trip, or take an approval back before the money goes out, with a reason (required). Reverses any posting. Needs expenses:approve.","auth":"jwt","body":{"reason":"Trip was for a personal errand"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/mileage/trips/{id}/pay","summary":"Mark a trip reimbursed. Posts the payment as its own entry (DR 2120 / CR the account named by bankAccountId, with a bank line on it; the pooled 1350 when none is named) on `date` - the day the money left; today when absent, never before the trip, never after today - beside the approval accrual. Only from approved, and terminal — a paid trip can no longer be edited. Needs expenses:approve.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripDate":"2026-09-01","origin":"sale","destination":"accounts@karoofresh.example","distanceKm":1.0,"ratePerKm":1.0,"claimAmount":10005.0,"purpose":"sale","vehicle":"CA 123-456","status":"sent","createdBy":"Thandi Mokoena","createdByName":"Thandi Mokoena","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/documents/inbox/{id}/bank-line-proposals","auth":"jwt","summary":"Unmatched bank lines of the same amount within a few days of this document. Proposals; nothing is filed.","responseExample":[{"bankTransactionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"OCEAN BASKET SANDTON","amount":1850.0,"daysApart":2,"sentence":"Ocean Basket is for the same amount and is dated 2 days earlier. Attach it to this line?"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/bills/{id}/approve","summary":"Approve a bill for payment. Needs expenses:approve; refused when it is paid, void, a credit note or already approved.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","kind":"standard","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customsReference":null,"openMarketValue":null}],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","paymentHold":"text","exchangeRate":1.0,"paymentFxRate":15.0,"baseGross":1.0,"approvalStatus":"approved","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","approvalProgress":{"given":1,"needed":1,"approverNames":["Thandi Mokoena"],"youApproved":false},"sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/{id}/reject","summary":"Send a bill back, with a reason. It stays owed and cannot be paid until it is corrected (which sends it back for approval) or voided.","auth":"jwt","body":{"reason":"Not our order — delivered to the wrong site"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","amount":10005.0,"vatAmount":1305.0,"vatRate":15.0,"currency":"ZAR","category":"Office supplies","status":"sent","recurring":false,"frequency":"monthly","nextDate":"2026-09-01","endDate":"2026-09-30","recurrenceActive":true,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","paidAt":"2026-09-01T09:15:00Z","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","kind":"standard","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"discountRate":0.0,"discountFixed":0.0,"lineTotal":10005.0,"vatAmount":1305.0,"category":"Office supplies","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customsReference":null,"openMarketValue":null}],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","paymentHold":"text","exchangeRate":1.0,"paymentFxRate":15.0,"baseGross":1.0,"approvalStatus":"approved","approvedBy":"Thandi Mokoena","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","approvalProgress":{"given":1,"needed":1,"approverNames":["Thandi Mokoena"],"youApproved":false},"sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/approval-limits","summary":"How much each role or person may approve in the active company. A person's own limit wins over their role's; the owner has none; with no limit a person approves any amount. mayChange is true for an owner or admin who can approve expenses.","auth":"jwt","responseExample":{"limits":[{"id":"6f1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","roleId":"0b6f2a3c-7d4e-4f5a-9b8c-1d2e3f4a5b6c","roleName":"Accountant","maxAmount":5000.0}],"mayChange":true},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/expenses/approval-limits","summary":"Set one role's or one person's approval limit (exactly one of roleId and userId); setting it again replaces it. An approval above the approver's limit is refused with 409, and a bill saved by somebody over their limit waits for an approver whose limit covers it. Owner or admin who can approve expenses; an approver may not set their own.","auth":"jwt","body":{"roleId":"0b6f2a3c-7d4e-4f5a-9b8c-1d2e3f4a5b6c","userId":null,"maxAmount":5000.0},"responseExample":{"limits":[{"id":"6f1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d","roleId":"0b6f2a3c-7d4e-4f5a-9b8c-1d2e3f4a5b6c","roleName":"Accountant","maxAmount":5000.0}],"mayChange":true},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/expenses/approval-limits/{id}","summary":"Remove an approval limit; that role or person can approve any amount again. Owner or admin who can approve expenses.","auth":"jwt","responseExample":{"limits":[],"mayChange":true},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/approval-policy","summary":"The amount from which an expense claim, mileage trip, per-diem claim or supplier bill needs a second approval from a different person.","auth":"jwt","responseExample":{"secondApprovalFrom":1.0,"approvers":1,"mayChange":false,"summary":"Consulting services — August 2026"},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/expenses/approval-policy","summary":"Set the second-approval amount, or turn it off with null. The owner or an admin who can approve expenses; refused while fewer than two people can approve.","auth":"jwt","body":{"secondApprovalFrom":10000.0},"responseExample":{"secondApprovalFrom":1.0,"approvers":1,"mayChange":false,"summary":"Consulting services — August 2026"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/payment-run?dueBy=2026-10-10&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"What a supplier payment run would pay: approved, owed bills due by the date, the ones it cannot pay with the reason, and the total.","auth":"jwt","responseExample":{"payable":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","dueDate":"2026-09-01","amount":10005.0,"payee":"text","blockedReason":"Budget deferred to the next financial year.","warning":"text"}],"blocked":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","dueDate":"2026-09-01","amount":10005.0,"payee":"text","blockedReason":"Budget deferred to the next financial year.","warning":"text"}],"total":10005.0,"dueBy":"text","fileNote":"Budget deferred to the next financial year."},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/bills/payment-runs","summary":"The company's supplier payment runs, newest first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payDate":"2026-09-01","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","total":10005.0,"billCount":3,"lines":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","beneficiaryName":"Karoo Fresh Holdings Ltd","payee":"text","amount":10005.0,"reference":"INV-0001"}],"createdByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z","fileName":"SignedPO-4417.pdf"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/bills/payment-runs","summary":"Pay the chosen bills in one run from one bank account, each through the bill's own pay path. All or nothing; the same clientId twice pays nothing twice.","auth":"jwt","body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payDate":"2026-09-01","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","total":10005.0,"billCount":3,"lines":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","beneficiaryName":"Karoo Fresh Holdings Ltd","payee":"text","amount":10005.0,"reference":"INV-0001"}],"createdByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z","fileName":"SignedPO-4417.pdf"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/payment-runs/{id}","summary":"One supplier payment run and the bills it paid.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payDate":"2026-09-01","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","total":10005.0,"billCount":3,"lines":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendor":"Karoo Fresh Holdings Ltd","billNumber":"INV-0001","beneficiaryName":"Highveld Provident Fund","payee":"text","amount":10005.0,"reference":"INV-0001"}],"createdByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z","fileName":"SignedPO-4417.pdf"},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/bills/payment-runs/{id}/bank-file?bank=fnb","summary":"The run's bank payment file. Without ?bank= the schedule (CSV: beneficiary name, account number, branch code, amount, reference); ?bank=fnb, standard-bank or investec is that bank's own upload layout, or 422 with blockingIssues naming what to fix. Downloaded, never sent to a bank.","auth":"jwt","responseKind":"text","module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/claim-run","summary":"What a claims run would pay now: every approved, unpaid expense, mileage and per-diem claim, each owed to an employee on the payroll, and those that cannot be paid in a run with the reason.","auth":"jwt","responseExample":{"payable":[{"kind":"standard","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","claimant":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","amount":10005.0,"status":"sent","stage":"text","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","blockedReason":"Budget deferred to the next financial year.","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"blocked":[{"kind":"standard","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","claimant":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","amount":10005.0,"status":"sent","stage":"text","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","blockedReason":"Budget deferred to the next financial year.","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"total":10005.0,"employeeCount":3},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/claim-runs","summary":"The company's claims runs, newest first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payDate":"2026-09-01","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","total":10005.0,"claimCount":3,"employeeCount":3,"createdAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/expenses/claim-runs","summary":"Pay the chosen staff claims in one run from one bank account, each through its own register's pay path. All or nothing; the same clientId twice pays nothing twice.","auth":"jwt","body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","claims":[{"kind":"expense","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payDate":"2026-09-01","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","total":10005.0,"claimCount":3,"employeeCount":3,"createdAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/expenses/claim-runs/{id}/bank-file?bank=fnb","summary":"The claims run's bank payment file, one line per employee. Without ?bank= the schedule; ?bank=fnb, standard-bank or investec is that bank's own upload layout, or 422 with blockingIssues naming what to fix. Downloaded, never sent to a bank.","auth":"jwt","responseKind":"text","module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/expenses/claims-report?from=2026-10-01&to=2026-10-31","summary":"Staff claims by employee and stage (waiting, owed, paid, rejected), optionally dated ?from= and ?to= (yyyy-MM-dd), each with its receipt and the run that paid it. The owed total is what account 2120 holds for claims.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","claims":[{"kind":"standard","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","claimant":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","amount":10005.0,"status":"sent","stage":"text","receiptUrl":"https://app.ledgrsa.com/pay/3f1a7c92","blockedReason":"Budget deferred to the next financial year.","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"byEmployee":[{"claimant":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","count":3,"owed":1.0,"paid":1.0}],"waiting":1.0,"owed":1.0,"paid":1.0,"rejected":1.0},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/suppliers/{id}/bank-details","summary":"A supplier's bank details, which a payment run pays into.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","bankName":"FNB","accountNumber":"62012345678","branchCode":"250655","accountType":"savings","updatedAt":"2026-09-01T09:15:00Z","updatedByName":"Thandi Mokoena","blocker":"text"},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/suppliers/{id}/bank-details","summary":"Set a supplier's bank details from their bank confirmation letter. Refused unless usable; the change is audited.","auth":"jwt","body":{"bankName":"FNB","accountNumber":"62012345678","branchCode":"250655","accountType":"current"},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","bankName":"FNB","accountNumber":"62012345678","branchCode":"250655","accountType":"savings","updatedAt":"2026-09-01T09:15:00Z","updatedByName":"Thandi Mokoena","blocker":"text"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/credit-notes?limit=50&billId=8ed9dcd6-0243-510c-a938-da741440b9ce","summary":"Supplier credit notes, newest first, optionally only those against one bill. A credit note is carried as a bill of kind credit_note with negative figures, so the ageing, the VAT201 and the supplier statement are reduced by it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","issueDate":"2026-09-01","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditedBillNumber":"CN-0001","supplierName":"Karoo Fresh Holdings Ltd","net":8700.0,"vat":1305.0,"total":10005.0,"settlement":"text","status":"sent","reason":"Budget deferred to the next financial year.","supplierReturnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","refundedAt":"2026-09-01T09:15:00Z"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/bills/{billId}/credit-notes","summary":"Raise the supplier's credit note against a bill: DR 2110 / CR the line's account (5020 for stock) / CR 1340. Against a bill still owed it is taken off that bill's payment; against a bill already paid the supplier owes the money until their refund is recorded. Refused beyond what the bill billed, in total or per order line.","auth":"jwt","body":{"creditNoteNumber":"CN-4471","issueDate":"2026-09-30","reason":"Price agreed down","lines":[{"description":"Argon 20kg","quantity":2.0,"unitPrice":400.0,"vatRate":15.0,"poLineId":"72c5521b-e186-531f-b4bd-196251336e28","category":"stock"}],"clientId":"453b20f0-8fc1-50d0-9471-51761784522b"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","issueDate":"2026-09-01","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditedBillNumber":"CN-0001","supplierName":"Karoo Fresh Holdings Ltd","net":8700.0,"vat":1305.0,"total":10005.0,"settlement":"text","status":"sent","reason":"Budget deferred to the next financial year.","supplierReturnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","refundedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/credit-notes/{id}/refund","summary":"Record the supplier's refund of a credit raised against a bill already paid: DR 1350 / CR 2110.","auth":"jwt","body":{"date":"2026-09-30"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","issueDate":"2026-09-01","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditedBillNumber":"CN-0001","supplierName":"Karoo Fresh Holdings Ltd","net":8700.0,"vat":1305.0,"total":10005.0,"settlement":"text","status":"sent","reason":"Budget deferred to the next financial year.","supplierReturnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","refundedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/bills/credit-notes/{id}/applicable-bills","summary":"The bills a standing supplier credit can come off: its supplier's, owed, in its currency, each with what is left to pay.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","dueDate":"2026-09-01","payable":1.0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/bills/credit-notes/{id}/apply","summary":"Apply a credit standing against no bill to the supplier's bill, whole or (a credit brought across at take-on) in part. Nothing posts: both are in 2110 already. It comes off that bill's payment, and a bill it covers whole is settled with no money moved.","auth":"jwt","body":{"billId":"8ed9dcd6-0243-510c-a938-da741440b9ce","amount":300.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","issueDate":"2026-09-01","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditedBillNumber":"CN-0001","supplierName":"Karoo Fresh Holdings Ltd","net":8700.0,"vat":1305.0,"total":10005.0,"settlement":"text","status":"due","reason":"Budget deferred to the next financial year.","supplierReturnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","refundedAt":"2026-09-01T09:15:00Z","applied":false,"openingBalance":false},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/credit-notes/{id}/unapply","summary":"Take an application back off its bill: the credit stands open again and the bill owes what it did. Refused while the bill stands paid.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/bills/credit-notes/{id}/void","summary":"Void a credit note that has not been settled; its journal is reversed and the bill owes what it did before.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","issueDate":"2026-09-01","creditedBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditedBillNumber":"CN-0001","supplierName":"Karoo Fresh Holdings Ltd","net":8700.0,"vat":1305.0,"total":10005.0,"settlement":"text","status":"sent","reason":"Budget deferred to the next financial year.","supplierReturnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","refundedAt":"2026-09-01T09:15:00Z"},"module":"expenses","plan":"Starter","scope":"expenses:write"}]},{"name":"Purchasing & suppliers","blurb":"The creditors mirror of the debtor side — orders, goods receipts, landed cost and supplier statement reconciliation.","endpoints":[{"method":"GET","path":"/api/purchase-orders?includeClosed=true","summary":"Purchase orders and the open commitment they represent.","auth":"jwt","responseExample":{"asOf":"text","orders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyOrdered":1.0,"qtyReceived":1.0,"qtyOutstanding":1.0,"unitPrice":2900.0}],"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptCount":3}],"totalOutstanding":10005.0,"openOrderCount":3},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/purchase-orders/{id}","summary":"One order with its lines and receipt history.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyOrdered":1.0,"qtyReceived":1.0,"qtyOutstanding":1.0,"unitPrice":2900.0}],"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptCount":3},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/purchase-orders/{id}/approve","summary":"Approve an order for transmission.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyOrdered":1.0,"qtyReceived":1.0,"qtyOutstanding":1.0,"unitPrice":2900.0}],"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptCount":3},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/purchase-orders/{id}/cancel","summary":"Cancel an order and release its commitment.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyOrdered":1.0,"qtyReceived":1.0,"qtyOutstanding":1.0,"unitPrice":2900.0}],"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptCount":3},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/{id}/revisions","summary":"Every earlier version of an order, newest first — what it said before each change made after it was approved or sent.","auth":"jwt","responseExample":[{"revision":0,"createdAt":"2026-09-01T10:15:00Z","changedByName":"Thandi Nkosi","netBefore":8700.0,"netAfter":11600.0,"returnedForApproval":true,"statusBefore":"approved","lines":[{"description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0}]}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/purchase-orders/{id}/lines/{lineId}/match-basis","summary":"Whether an invoice for this order line needs a delivery behind it: true matches it to the order alone, false requires a receipt, null returns it to the default.","auth":"jwt","body":{"matchOnOrder":true},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"approved","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":3.0,"qtyReceived":0.0,"qtyOutstanding":3.0,"unitPrice":2900.0,"matchOnOrder":true,"matchOnOrderSet":true}],"receiptCount":0,"revision":0},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/{id}/receipts","summary":"What has been received against this order.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","deliveryNoteRef":"INV-0001","notes":"Budget deferred to the next financial year.","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyReceived":1.0,"unitCost":2900.0,"lineTotal":8700.0,"batchNumber":"INV-0001"}],"total":10005.0}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/purchase-orders/{id}/receive","summary":"Receive goods. The stock movement is dated the RECEIPT date, not the day it was keyed — the journal already was, so a backdated capture used to put stock and the GL in different periods for one event.","auth":"jwt","responseExample":{"receipt":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","deliveryNoteRef":"INV-0001","notes":"Budget deferred to the next financial year.","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyReceived":1.0,"unitCost":2900.0,"lineTotal":8700.0,"batchNumber":"INV-0001"}],"total":10005.0},"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"clientId":"b8fb24bf-f65e-5730-8c45-a314ee0bb216","fxRate":18.5,"receiptDate":"2026-09-30","lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyReceived":2.0,"unitCost":2900.0,"batchNumber":"INV-0001","expiryDate":"2026-09-01"}],"deliveryNoteRef":"INV-0001","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","createBill":true},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/drop-ship?salesInvoiceId=afc5d92b-ef69-5faf-9611-ed55708cd855","summary":"Drop-ship orders — for one sale, or every one still open. A drop-shipped line moves no stock: the supplier delivers to the customer, and their despatch is the cost of the sale.","auth":"jwt","responseExample":{"orders":[{"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","status":"sent","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","salesInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","salesInvoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","deliveryAddress":"12 Long Street, Cape Town, 8001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"qtyDespatched":1.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/purchase-orders/drop-ship","summary":"Drop-ship one product line of a tax invoice: a draft order to the product's approved supplier, addressed to the customer. The sale stops taking those goods off the shelf; confirming the supplier's despatch (receive) raises their bill against cost of sales, never through inventory.","auth":"jwt","body":{"productId":"8f5dddde-b378-584b-8d66-7d9bc57fa970","supplierId":"118cb679-0914-5f4a-a2e4-55b1ae1f3ab5","unitCost":400.0,"salesInvoiceId":"2ece2ebc-6815-58cc-88ec-bb446dc413d1","lineId":"c0c15f3f-cb19-5207-a739-531ddb52a122","deliveryAddress":"12 Church Street, Graaff-Reinet, 6280"},"responseExample":{"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","status":"sent","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","salesInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","salesInvoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","deliveryAddress":"12 Long Street, Cape Town, 8001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"qtyDespatched":1.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/landed-costs","summary":"Landed-cost dockets — freight, duty and clearing waiting to be apportioned into stock.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"text","customsMrn":"text","allocationMethod":"eft","status":"sent","totalCharges":10005.0,"totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"receiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"receiptNumbers":["INV-0001"],"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"isPreview":true,"uncapitalised":1.0,"warnings":[]}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/landed-costs","summary":"Open a docket against one or more goods receipts.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"text","customsMrn":"text","allocationMethod":"eft","status":"sent","totalCharges":10005.0,"totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"receiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"receiptNumbers":["INV-0001"],"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"isPreview":true,"uncapitalised":1.0,"warnings":[]},"body":{"clientId":"4ea78728-ddfd-5b57-8fd4-e58dca8360d6","docketNumber":"SHIP-2026-14","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"MSC AURORA / MEDU1234567","customsMrn":"26ZADUR00012345","allocationMethod":"eft","notes":"Budget deferred to the next financial year.","charges":[{"chargeType":"standard","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":18400.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"goodsReceiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/landed-costs/{id}","summary":"One docket and its apportionment.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"text","customsMrn":"text","allocationMethod":"eft","status":"sent","totalCharges":10005.0,"totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"receiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"receiptNumbers":["INV-0001"],"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"isPreview":true,"uncapitalised":1.0,"warnings":[]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/landed-costs/{id}","summary":"Change a docket before it is posted.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"text","customsMrn":"text","allocationMethod":"eft","status":"sent","totalCharges":10005.0,"totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"receiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"receiptNumbers":["INV-0001"],"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"isPreview":true,"uncapitalised":1.0,"warnings":[]},"body":{"clientId":"bb866a9b-544a-5857-b5ef-3dc5e39b4fc7","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"MSC AURORA / MEDU1234567","customsMrn":"26ZADUR00012345","allocationMethod":"eft","notes":"Budget deferred to the next financial year.","charges":[{"chargeType":"standard","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":9200.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"goodsReceiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/landed-costs/{id}","summary":"Discard an unposted docket.","auth":"jwt","responseExample":{"status":"deleted"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/landed-costs/bill-options?q=dcf","summary":"Supplier invoices that can be linked to a landed-cost charge — live bills, newest first, by number or supplier.","auth":"jwt","responseExample":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"DCF-9001","vendor":"Durban Clearing & Forwarding","issueDate":"2026-10-12","amount":2300.0,"currency":"ZAR","status":"due"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/landed-costs/{id}/charges/{chargeId}/bill","summary":"Link the agent's invoice to a charge (or unlink it with null), on a draft or a posted docket; a posted docket's accrual is then cleared by that bill.","auth":"jwt","bodyExample":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"SAD500-0001","status":"posted"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/landed-costs/{id}/post","summary":"Apportion the cost into the batches it brought in and raise the journal.","auth":"jwt","responseExample":{"docketId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"linesAdjusted":1,"batchesAdjusted":1,"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"warnings":[]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/landed-costs/{id}/bill","summary":"Link the clearing agent's bill, keyed in Bills, to the docket's charges that name no bill yet, and re-post it: the bill then debits 2120 for what the docket accrued instead of expensing the same freight, duty and import VAT a second time. Refused for a bill in another currency or a docket with nothing left to link.","auth":"jwt","body":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","docketNumber":"INV-0001","docketDate":"2026-09-01","description":"Consulting services — August 2026","vesselOrWaybill":"text","customsMrn":"text","allocationMethod":"eft","status":"sent","totalCharges":10005.0,"totalCapitalised":10005.0,"totalExpensed":10005.0,"totalRecoverable":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postedAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"capitalise":true,"expenseAccountCode":"CT-001"}],"receiptIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"receiptNumbers":["INV-0001"],"allocations":[{"goodsReceiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"invoiceUnitCost":2900.0,"lineValue":10005.0,"basisAmount":10005.0,"allocatedAmount":10005.0,"landedUnitCost":2900.0,"unitCostBefore":2900.0,"unitCostAfter":2900.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","capitalisable":true}],"isPreview":true,"uncapitalised":1.0,"warnings":[]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/landed-costs/defaults","summary":"Standing cost types and their apportionment basis.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productSku":"LEN-TP-14G4","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","percentOfValue":15.0,"capitalise":true,"active":true,"notes":"Budget deferred to the next financial year.","specificity":3}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/landed-costs/defaults","summary":"Add a cost type.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productSku":"LEN-TP-14G4","chargeType":"standard","label":"Karoo Fresh Holdings Ltd","percentOfValue":15.0,"capitalise":true,"active":true,"notes":"Budget deferred to the next financial year.","specificity":3}],"body":{"clientId":"0a4f4aa1-b7dc-59cc-9cd4-fd01927b8fb9","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","chargeType":"freight","percentOfValue":15.0,"capitalise":true,"active":true,"notes":"Budget deferred to the next financial year."},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/landed-costs/defaults/{id}","summary":"Remove a cost type.","auth":"jwt","responseExample":{"status":"deleted"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/landed-costs/receipt-options?q=umhlanga","summary":"Goods receipts a docket can still be attached to.","auth":"jwt","responseExample":[{"goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","supplierName":"Karoo Fresh Holdings Ltd","deliveryNoteRef":"INV-0001","lineCount":3,"totalValue":10005.0,"landedCostAlready":10005.0}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/suppliers/aged?asOf=2027-02-28","summary":"Aged creditors by bucket.","auth":"jwt","responseExample":[{"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","asOf":"text","lines":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","total":10005.0,"outstanding":1.0,"daysOverdue":30,"category":"Office supplies"}],"totalOutstanding":10005.0,"current":1.0,"days30":1.0,"days60":1.0,"days90Plus":1.0,"oldestDays":30}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/suppliers/{id}/statement?asOf=2027-02-28","summary":"A supplier statement as data.","auth":"jwt","responseExample":{"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","asOf":"text","lines":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","total":10005.0,"outstanding":1.0,"daysOverdue":30,"category":"Office supplies"}],"totalOutstanding":10005.0,"current":1.0,"days30":1.0,"days60":1.0,"days90Plus":1.0,"oldestDays":30},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/suppliers/{id}/statement.pdf?asOf=2027-02-28","summary":"The same statement as a PDF.","auth":"jwt","responseKind":"pdf","module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/suppliers/{id}/send-statement","summary":"Send a remittance or statement to the supplier.","auth":"jwt","responseExample":{"delivered":true,"channel":"email","error":"text"},"body":{"channel":"email","message":"Saved."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/suppliers/{id}/reconcile","summary":"Reconcile the supplier's own statement against what Ledgr holds, and report the differences.","auth":"jwt","responseExample":{"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","asOf":"text","ourBalance":10005.0,"theirBalance":10005.0,"difference":1.0,"agreed":true,"openItems":[{"reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","outstanding":1.0,"daysOverdue":30,"raisedAfterTheirStatement":false}],"itemsRaisedAfterTheirStatement":1,"valueRaisedAfterTheirStatement":10005.0},"body":{"supplierBalance":1500.0,"asOf":"2026-09-30","supplierStatementDate":"2026-09-01"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/receipts/recent?limit=50","summary":"The deliveries booked lately, newest first, with whether anything on each can still go back to the supplier and whether any of it is held for inspection. Bounded.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","total":10005.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","canReturn":true,"awaitingInspection":true}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/purchase-orders/receipts/{receiptId}","summary":"One delivery with everything that has happened to it since: per line what can still go back, what is held for inspection, what was rejected and not yet returned, and the returns already booked.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","deliveryNoteRef":"INV-0001","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","billStatus":"sent","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyReceived":1.0,"unitCost":2900.0,"batchNumber":"INV-0001","expiryDate":"2026-09-01","qtyReturned":1.0,"returnable":1.0,"inspectionStatus":"sent","qtyAccepted":1.0,"qtyRejected":1.0,"rejectionReason":"Budget deferred to the next financial year.","awaitingInspection":1.0,"rejectedNotReturned":1.0,"qtyPrecision":3,"vatRate":15.0}],"returns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","returnNumber":"INV-0001","returnDate":"2026-09-01","receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","resolution":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"creditValue":10005.0,"stockValue":10005.0}],"creditNoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","creditTotal":10005.0,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."}]},"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/purchase-orders/receipts/{receiptId}/returns","summary":"Send goods back to the supplier. Each line is drawn from the batch it came in on, at that batch's own cost (DR 5020 / CR 1310, any landed cost the supplier does not refund to 5070), and — where the delivery is billed — the supplier's credit note is raised against that bill in the same step. Refused if the goods are no longer in that batch.","auth":"jwt","body":{"notes":"Two cylinders leaking at the valve","returnDate":"2026-09-30","reason":"Damaged on arrival","resolution":"credit","lines":[{"receiptLineId":"e02873ce-3aa1-51c4-9e5b-e894da93d666","qty":2.0}],"raiseCreditNote":true,"creditNoteNumber":"CN-4471","clientId":"7f9a9036-aa16-5e27-b15d-e22b36a84861"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","returnNumber":"INV-0001","returnDate":"2026-09-01","receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","resolution":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"creditValue":10005.0,"stockValue":10005.0}],"creditNoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","creditTotal":10005.0,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/purchase-orders/receipts/{receiptId}/inspection","summary":"Record an inspection of goods held on receipt: accepted units are released to stock, rejected ones stay held until they go back. Accepted and rejected must account for every held unit, and a rejection needs a reason. `returnRejected` books the return (and its credit note) in the same step.","auth":"jwt","body":{"lines":[{"receiptLineId":"9ee0b73c-c65d-5cbc-bbe2-0c3b98b97078","qtyAccepted":8.0,"qtyRejected":2.0,"reason":"Leaking valve"}],"returnRejected":true,"returnDate":"2026-09-30"},"responseExample":{"receipt":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","deliveryNoteRef":"INV-0001","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","billStatus":"sent","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyReceived":1.0,"unitCost":2900.0,"batchNumber":"INV-0001","expiryDate":"2026-09-01","qtyReturned":1.0,"returnable":1.0,"inspectionStatus":"sent","qtyAccepted":1.0,"qtyRejected":1.0,"rejectionReason":"Budget deferred to the next financial year.","awaitingInspection":1.0,"rejectedNotReturned":1.0,"qtyPrecision":3,"vatRate":15.0}],"returns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","returnNumber":"INV-0001","returnDate":"2026-09-01","receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","resolution":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"creditValue":10005.0,"stockValue":10005.0}],"creditNoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","creditTotal":10005.0,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."}]},"released":1.0,"rejected":1.0,"supplierReturn":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","returnNumber":"INV-0001","returnDate":"2026-09-01","receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","resolution":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"creditValue":10005.0,"stockValue":10005.0}],"creditNoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","creditTotal":10005.0,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."}},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/inspection-queue","summary":"Every delivered line held for inspection, oldest first — valued and in stock, but not available to sell, issue or build with until inspected.","auth":"jwt","responseExample":[{"receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","receiptDate":"2026-09-01","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","awaiting":1.0,"unitCost":2900.0,"qtyPrecision":3,"batchNumber":"INV-0001"}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/purchase-orders/inspection/products","summary":"The products whose deliveries are held for inspection on receipt.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","inspectOnReceipt":true}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"PUT","path":"/api/purchase-orders/inspection/products/{productId}","summary":"Turn inspect-on-receipt on or off for a product. Needs inventory:edit — it is a fact about the goods.","auth":"jwt","body":{"inspectOnReceipt":true},"responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","inspectOnReceipt":true},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/purchase-orders/returns?limit=50","summary":"Returns to supplier, newest first, with the credit note each raised. Bounded.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","returnNumber":"INV-0001","returnDate":"2026-09-01","receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"INV-0001","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","supplierName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","resolution":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitCost":2900.0,"creditValue":10005.0,"stockValue":10005.0}],"creditNoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","creditNoteNumber":"CN-0001","creditTotal":10005.0,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"GET","path":"/api/purchase-orders/{id}/scan?code=6001234567890","summary":"What a scanned or typed code is against this order: the product it names (barcode first, then SKU), whether it is on the order, and whether to ask for a batch number and expiry. A product not on the order is named in the refusal.","auth":"jwt","responseExample":{"code":"CT-001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","onOrder":true,"asksForBatch":true,"message":"Saved."},"module":"expenses","plan":"Starter","scope":"expenses:read"}]},{"name":"Banking & reconciliation","blurb":"Bank data enters two ways. Investec is the one South African bank a customer can connect to on their own — they mint their own client id, secret and API key in Investec Online, so Ledgr needs no agreement with the bank. Every other bank's data arrives as a statement: uploaded here, or emailed to the company's inbox address and imported by itself once it reconciles to the closing balance the bank printed.","endpoints":[{"method":"GET","path":"/api/bank-feeds","summary":"This company's Investec feeds, plus whether a feed can be connected at all and how to get the keys.","auth":"jwt","responseExample":{"feeds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","investecAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","investecAccountName":"Karoo Fresh Holdings Ltd","investecAccountMasked":"text","currency":"ZAR","status":"active","statusLabel":"Karoo Fresh Holdings Ltd","lastSyncAt":"2026-09-01T09:15:00Z","lastSyncStatus":"sent","lastError":"text","syncCount":3,"totalImported":1,"consecutiveFailures":1,"nextAttemptAt":"2026-09-01T09:15:00Z","syncFrom":"2026-09-01","createdAt":"2026-09-01T09:15:00Z","needsAttention":false,"attentionReason":"Budget deferred to the next financial year."}],"availability":{"secretStorageReady":true,"secretStorageHint":"text","developerPortalUrl":"https://app.ledgrsa.com/pay/3f1a7c92","requiredFields":["text"],"instructions":["text"]},"activeCount":3,"attentionCount":3},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-feeds","summary":"Connect a feed with your own Investec client id, secret and API key. They are proved against Investec before they are stored, and the reply carries the accounts they can see.","auth":"jwt","responseExample":{"feedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"active","accounts":[{"investecAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","masked":"text","currency":"ZAR","linkedBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","suggestedBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"message":"Saved."},"body":{"clientId":"<your Investec client id>","clientSecret":"<your Investec client secret>","apiKey":"<your Investec API key>","syncFrom":"2026-06-01"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-feeds/{id}/accounts","summary":"Re-read the Investec account list, with a suggested Ledgr account matched by account number.","auth":"jwt","responseExample":[{"investecAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","masked":"text","currency":"ZAR","linkedBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","suggestedBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-feeds/{id}/link","summary":"Map an Investec account onto a Ledgr bank account. An unmapped feed imports nothing rather than guessing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","investecAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","investecAccountName":"Karoo Fresh Holdings Ltd","investecAccountMasked":"text","currency":"ZAR","status":"active","statusLabel":"Karoo Fresh Holdings Ltd","lastSyncAt":"2026-09-01T09:15:00Z","lastSyncStatus":"sent","lastError":"text","syncCount":3,"totalImported":1,"consecutiveFailures":1,"nextAttemptAt":"2026-09-01T09:15:00Z","syncFrom":"2026-09-01","createdAt":"2026-09-01T09:15:00Z","needsAttention":false,"attentionReason":"Budget deferred to the next financial year."},"body":{"investecAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-feeds/{id}/sync","summary":"Pull now. Idempotent — Investec's own transaction id plus a content signature, so nothing imports twice.","auth":"jwt","responseExample":{"feedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"active","fetched":1,"imported":1,"duplicates":1,"rejected":0,"message":"Saved."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-feeds/{id}/runs","summary":"The sync history, newest first. A feed that silently stops is worse than no feed.","auth":"jwt","responseExample":{"feedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","trigger":"text","status":"active","startedAt":"2026-09-01T09:15:00Z","finishedAt":"2026-09-01T09:15:00Z","fetched":1,"imported":1,"duplicates":1,"rejected":0,"error":"text"}]},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"DELETE","path":"/api/bank-feeds/{id}","summary":"Disconnect and erase the stored Investec keys. Transactions already imported are kept.","auth":"jwt","responseExample":{"ok":true,"message":"Saved."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-accounts?includeClosed=true","summary":"Bank accounts with balances and sparkline trends.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"statementBalance":10005.0,"type":"standard","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-accounts/unattributed","summary":"What the books hold on the bank control that no account claims: payments posted without naming the account they went into. Banking adds it to the accounts' total in the books.","auth":"jwt","responseExample":{"amount":930802.31},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-accounts","summary":"Add an account. Nine SA banks are supported for import. Send your own clientId (a UUID) and a retry after a lost response returns the account the first request added instead of adding it twice.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"statementBalance":10005.0,"type":"standard","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Karoo Fresh Holdings Ltd","accountNumber":"62811234567","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"type":"cheque","clientId":"8b2f0c4e-1d7a-4e3b-9c55-6a0f2e7d1b94"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-accounts/{id}","summary":"One account.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","statementBalance":10005.0,"currentBalance":10005.0,"type":"standard","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"PUT","path":"/api/bank-accounts/{id}","summary":"Update an account.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"statementBalance":10005.0,"type":"standard","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"statementCadenceDays":31,"name":"FNB Business Cheque (main)","accountNumber":"62012345678","bankName":"FNB","currentBalance":10005.0,"type":"standard","currency":"ZAR"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"DELETE","path":"/api/bank-accounts/{id}","summary":"Remove an account.","auth":"jwt","responseKind":"none","module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-accounts/{id}/close","summary":"Close an account the business no longer uses. Its transactions and reconciliations stay readable; it leaves the account lists and the cash position and takes no new lines. Refused while a reconciliation is open, a bank feed is connected, or a line is dated after the closing date.","auth":"jwt","body":{"closedOn":"2026-08-31"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"statementBalance":10005.0,"type":"standard","closedOn":"2026-08-31","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-accounts/{id}/reopen","summary":"Reopen a closed account, exactly as it was.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","accountNumber":"62012345678","bankName":"FNB","currency":"ZAR","currentBalance":10005.0,"statementBalance":10005.0,"type":"standard","closedOn":null,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-transactions?accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&status=unmatched","summary":"Transactions for an account.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","type":"standard","status":"UNRECONCILED","matchedInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","matchedExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","source":"referral","autoCreatedKind":"standard","autoCreatedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-transactions","summary":"Key a transaction by hand.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","type":"standard","status":"UNRECONCILED","matchedInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","matchedExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","source":"referral","autoCreatedKind":"standard","autoCreatedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-08-14","description":"PAYFAST ACME","amount":51750.0,"reference":"INV-0001","type":"CREDIT","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-transactions/{id}","summary":"One transaction and its match state.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","type":"standard","status":"UNRECONCILED","matchedInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","matchedExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","source":"referral","autoCreatedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","autoCreatedKind":"standard","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"DELETE","path":"/api/bank-transactions/{id}","summary":"Delete a transaction.","auth":"jwt","responseKind":"none","module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/import?accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&dateCol=1&descCol=1&amountCol=1&debitCol=1&creditCol=1&refCol=1&hasHeader=true&delimiter=tab&filename=fnb-cheque-september.tsv","summary":"Import transactions already parsed into Ledgr's shape. TransactionDedupe matches a hand-keyed row against an uploaded one.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactions":[{"date":"2026-08-14","description":"PAYFAST ACME","amount":51750.0}]},"responseExample":{"imported":1,"duplicates":1,"errors":[]},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/{id}/match","summary":"Match a transaction to an invoice or a bill. Money in settles an invoice; money out matched to an issued credit note records the customer's refund against it, and unmatching takes the refund back out. Money in is never matched to a credit note. Money out matched to a bill pays what the line moved: a line for all that the bill still owes settles it, a line for less is a part payment on it (the bill stays due, owing the rest), a line for more is refused (409); unmatching takes a part payment back off the bill.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","type":"standard","status":"UNRECONCILED","matchedInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","matchedExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","source":"referral","autoCreatedKind":"standard","autoCreatedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"body":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payrollPeriodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createExpense":false,"vatRate":15.0},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/{id}/unmatch","summary":"Break a match.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","type":"standard","status":"UNRECONCILED","matchedInvoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","matchedExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","source":"referral","autoCreatedKind":"standard","autoCreatedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/reconciliation/{id}/report","summary":"One reconciliation as a report: cleared items, the items the bank has not shown yet, and the tie to the books.","auth":"jwt","responseExample":{"sessionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountName":"FNB Business Cheque","ledgerCode":"1350-01","from":"2026-09-01","to":"2026-09-30","status":"FINALISED","statementOpening":0.0,"statementClosing":4000.0,"cleared":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-07","description":"INTERNET DEBIT ORDER","reference":null,"amount":-1000.0,"matchedTo":"6240 Telephone & Internet"}],"unclearedOut":[{"id":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","date":"2026-09-28","description":"CHEQUE 4471 SUPPLIER","reference":null,"amount":-300.0,"matchedTo":"6180 Repairs & Maintenance"}],"unclearedIn":[],"bookBalance":3700.0,"currency":"ZAR","notInBooks":[],"notInBooksTotal":0.0,"clearedTotal":4000.0,"unclearedOutTotal":-300.0,"unclearedInTotal":0.0,"tie":{"expectedBookBalance":3700.0,"bookBalance":3700.0,"difference":0.0,"ties":true,"sentence":"The books agree with the statement once the uncleared items are allowed for."}},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-transactions/{id}/transfer-candidates","summary":"The lines that could be the other side of this one.","auth":"jwt","responseExample":{"candidates":[{"id":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","bankAccountId":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","bankAccountName":"Standard Bank Business Savings","date":"2026-09-14","description":"TRANSFER FROM CHEQUE","amount":5000.0,"currency":"ZAR","type":"CREDIT","daysApart":0,"why":"The same figure, the other way, on the same day."}],"refusal":null,"note":null,"transfer":null,"awaitingTransfers":[]},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-transfers","summary":"Record a transfer between two of the tenant's own bank accounts.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromBankAccountName":"FNB Business Cheque","toBankAccountId":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","toBankAccountName":"Standard Bank Business Savings","transferDate":"2026-09-14","amountOut":5000.0,"amountIn":5000.0,"currency":"ZAR","outLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","inLineId":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","summary":"R 5 000.00 from FNB Business Cheque to Standard Bank Business Savings on 14 Sep 2026.","ledgerNotice":null,"awaitingOtherSide":false},"body":{"id":"e8b1c4d7-6a29-4f3e-9c05-1d7a8b2e4f63","outLineId":"6f3c2a91-4d7e-4b08-9a15-3c8e2f7d1b40","inLineId":"b27e9d04-1c6a-4e3f-8d52-9a0c7e4f6b13","fromBankAccountId":"4e8a1c73-9b2d-4f65-a0e7-5d3b8c1f2a96","toBankAccountId":"c93f5e28-7a14-4d0b-b6e9-2f8a0d4c7e51"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transfers/{id}/complete","summary":"Attach the second side to a transfer recorded from one line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromBankAccountName":"FNB Business Cheque","toBankAccountId":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","toBankAccountName":"Standard Bank Business Savings","transferDate":"2026-09-14","amountOut":5000.0,"amountIn":5000.0,"currency":"ZAR","outLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","inLineId":"8c2d5e41-77b9-4a30-8e15-9f6b1d2c4a07","summary":"R 5 000.00 from FNB Business Cheque to Standard Bank Business Savings on 14 Sep 2026.","ledgerNotice":null,"awaitingOtherSide":false},"body":{"lineId":"2a7d4f19-8e3c-4b60-9d1a-6c5e0f8b3a27"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"DELETE","path":"/api/bank-transfers/{id}","summary":"Take a recorded transfer back — one reversal, both lines freed.","auth":"jwt","responseExample":{"ledgerNotice":"The reversal is dated 1 Oct 2026, because September is closed."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-transactions/card-receipts-in-transit","summary":"Card payments a gateway still holds: paid by link, waiting in 1366 Card Payments in Transit until the payout line settles them. A row with refund:true is a refund an online store gave its buyer and keeps back from its payout: it comes OFF the payout, and the settle names it as cardRefundId rather than cardReceiptId.","auth":"jwt","responseExample":[{"id":"9b2d4e61-7a3c-4f08-b5e2-6c1a8d3f0e94","invoiceId":"d15b8e42-3f9a-4c07-8e26-1b7d9a0c5f38","invoiceNumber":"INV-2026-001","customerName":"Umhlanga Florist","gateway":"YOCO","paidOn":"2026-10-05","amount":1150.0,"refund":false}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-transactions/driver-cash-banked","summary":"Drivers' cash the office banked that no statement line has matched yet: the deposit line settles it, posting nothing, because banking it already put it in the bank.","auth":"jwt","responseExample":[{"id":"4c8e2a17-9d3b-4f61-a0e5-7b2c9d1e3f48","driverName":"Sipho Driver","bankAccountId":"0a7d3e92-5b1c-4e86-9f24-3c8b6a1d7e05","bankAccountName":"FNB Business Cheque","bankedOn":"2026-10-08","reference":"Deposit slip 0042","amount":1000.0}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-transactions/{id}/settle","summary":"Settle several documents from one line, with an optional adjustment for the difference. On a store's payout a part may be a refund the store kept back (cardRefundId): it comes off the line, so the card receipts less the refunds less the fee on the adjustment are the line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","settled":["INV-2026-001","INV-2026-002"],"ledgerNotice":"R 3 450.00 settled 2 documents."},"body":{"allocations":[{"invoiceId":"d15b8e42-3f9a-4c07-8e26-1b7d9a0c5f38","amount":1150.0},{"invoiceId":"7c0e3a56-2b8f-4d91-a4c3-8e6f1d2b9a07","amount":2300.0}],"adjustment":{"accountCode":"6030","amount":-4.5,"description":"Bank charge on receipt"}},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/{id}/on-behalf","summary":"Book a money-out line as paid on behalf of another company of the group: this company's bank and an intercompany receivable, the other company's expense and an intercompany payable, and the register row — in one transaction. Unmatch takes all of it back out.","auth":"jwt","body":{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"6090","vatRatePercent":15.0,"description":"Municipal rates, Erf 1201","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies","ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/{id}/code","summary":"Post a bank line to an account, or split it across several. Refused (400) for 2110, 1320, 1360, 1310, 1315 and 2115: each is the total of a register or a list, so a line is matched to the bill or invoice, recorded as a petty cash float or posted as stock, never coded straight to it. Money out coded to 5020 Purchases can name productId and quantity on a part: it clears those goods from 2115 Goods Received Not Invoiced (one line at a time, not in a bulk coding).","auth":"jwt","body":{"splits":[{"accountCode":"6120","vatRatePercent":15.0,"amount":1380.0},{"accountCode":"6150","vatRatePercent":0.0,"percent":40.0}],"memo":"Bank charges and the branch's share","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"6120 Bank Charges","ledgerNotice":"R 1 380.00 posted to 6120 Bank Charges."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/code","summary":"Code several lines to the same account in one act. All or nothing.","auth":"jwt","responseExample":{"coded":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"6120 Bank Charges","ledgerNotice":"R 1 380.00 posted to 6120 Bank Charges."}],"ledgerNotice":"1 line coded to 6120."},"body":{"ids":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"splits":[{"accountCode":"6120","vatRatePercent":15.0,"percent":100.0}],"memo":"Fuel for the Cape Town delivery run","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-statements/profiles","summary":"Column-mapping profiles for the nine supported banks, plus any the tenant has saved.","auth":"jwt","responseExample":{"banks":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"defaultBank":"FNB","defaultBankLabel":"Karoo Fresh Holdings Ltd","migrationSource":"referral"},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-statements/preview?filename=SignedPO-4417.pdf&accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&bank=fnb","summary":"Parse an uploaded CSV, OFX or QIF and show what would be imported, without writing.","auth":"jwt","responseExample":{"format":"CSV","detected":"text","accountReference":"INV-0001","currency":"ZAR","statementStart":"2026-09-01","statementEnd":"2026-09-30","openingBalance":10005.0,"closingBalance":10005.0,"bankProfile":{"bank":"FNB","label":"Karoo Fresh Holdings Ltd","confidence":1.0,"evidence":["text"],"matched":false,"source":"referral"},"total":42,"newCount":3,"duplicateCount":3,"balances":true,"balanceDifference":10005.0,"rows":[{"date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","runningBalance":10005.0}],"issues":[],"warnings":[],"documentText":"text","pageCount":3,"pagesRead":1,"truncated":false,"exactText":false,"readBy":"text"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-statements/convert?filename=SignedPO-4417.pdf&accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&bank=fnb","summary":"Turn the PDF or scan your bank sent into a statement. Multipart upload; answers with the transactions, whether they reconcile to the bank's own closing balance, and the text to post to /import. A locked PDF answers 200 with passwordRequired true and no rows (passwordRefused true when the password given did not open it): send it again with its password in the `password` form field, of at most 128 characters, used for that read only and kept nowhere. rowDoubts lists rows that contradict what they print; balances is false for those even at a nil difference.","auth":"jwt","responseExample":{"format":"CSV","detected":"text","accountReference":"INV-0001","currency":"ZAR","statementStart":"2026-09-01","statementEnd":"2026-09-30","openingBalance":10005.0,"closingBalance":10005.0,"bankProfile":{"bank":"FNB","label":"Karoo Fresh Holdings Ltd","confidence":1.0,"evidence":["text"],"matched":false,"source":"referral"},"total":42,"newCount":3,"duplicateCount":3,"balances":true,"balanceDifference":10005.0,"rows":[{"date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"reference":"INV-0001","runningBalance":10005.0}],"issues":[],"warnings":[],"documentText":"text","pageCount":3,"pagesRead":1,"truncated":false,"exactText":false,"readBy":"text"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-statements/import?filename=SignedPO-4417.pdf&accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&bank=fnb","summary":"Commit a parsed statement. A statement with rows in rowDoubts answers 409 with code STATEMENT_ROWS_IN_DOUBT until confirmRowDoubts=true says a person has seen them.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","profile":"fnb-csv"},"responseExample":{"format":"CSV","total":2,"imported":1,"duplicates":1,"rejected":0,"balances":true,"balanceDifference":10005.0,"bankProfile":{"bank":"FNB","label":"Karoo Fresh Holdings Ltd","confidence":1.0,"evidence":["text"],"matched":false,"source":"referral"},"issues":[],"warnings":[],"message":"Saved."},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-statements/export?format=csv&from=2026-03-01&to=2027-02-28&accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Export transactions back out as CSV.","auth":"jwt","responseKind":"csv","module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-rules","summary":"Auto-categorisation rules.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","conditions":"text","action":"created","priority":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-rules","summary":"Create a rule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","conditions":"text","action":"created","priority":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Parking and toll fees","conditions":[{"field":"description","op":"contains","value":"PARKING|TOLL"}],"action":{"category":"Travel","createKind":"expense","accountCode":"6120"},"priority":1,"matchMode":"all","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","applyOnImport":false,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-rules/{id}","summary":"One rule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","conditions":"text","action":"created","priority":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"PUT","path":"/api/bank-rules/{id}","summary":"Update a rule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","conditions":"text","action":"created","priority":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Karoo Fresh Holdings Ltd","conditions":[{"field":"description","op":"contains","value":"PARKING|TOLL"}],"action":{"category":"Travel","createKind":"expense","accountCode":"6120"},"priority":1,"isActive":true,"matchMode":"all","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clearBankAccount":false,"applyOnImport":true},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"PUT","path":"/api/bank-rules/order","summary":"Set the order the rules are tried in, most important first. The first rule that matches a line wins.","auth":"jwt","body":{"ruleIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","conditions":"text","action":"created","priority":1,"isActive":true,"matchMode":"all","bankAccountId":null,"applyOnImport":false,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"DELETE","path":"/api/bank-rules/{id}","summary":"Delete a rule.","auth":"jwt","responseKind":"none","module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-rules/preview","summary":"Show what the rules would do to the unreconciled transactions, before doing it.","auth":"jwt","responseExample":{"matched":1,"categorised":1,"created":1,"skipped":1,"dryRun":true,"outcomes":[{"transactionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","amount":10005.0,"ruleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ruleName":"Karoo Fresh Holdings Ltd","category":"Office supplies","createKind":"standard","createdId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","skippedReason":"Budget deferred to the next financial year."}]},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-rules/apply","summary":"Apply the rules, creating the transactions they imply.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"matched":1,"categorised":1,"created":1,"skipped":1,"dryRun":true,"outcomes":[{"transactionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","amount":10005.0,"ruleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ruleName":"Karoo Fresh Holdings Ltd","category":"Office supplies","createKind":"standard","createdId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","skippedReason":"Budget deferred to the next financial year."}]},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-rules/coded?includeReviewed=false","summary":"The review queue: lines a bank rule coded that nobody has reviewed yet (reconciled lines are never listed). includeReviewed=true adds the reviewed ones.","auth":"jwt","responseExample":{"total":1,"lines":[{"transactionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"type":"DEBIT","category":"Office supplies","status":"UNRECONCILED","ruleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ruleName":"Karoo Fresh Holdings Ltd","createdKind":"expense","createdId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ruleAppliedAt":"2026-09-01T09:15:00Z"}]},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-rules/coded/review","summary":"Confirm the lines a rule coded: they leave the review queue. Send the ids, or all=true for every line waiting. A rule that codes a line again puts it back.","auth":"jwt","body":{"ids":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"all":false},"responseExample":{"reviewed":1},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/reconciliation?bankAccountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&status=open","summary":"Reconciliation sessions and their status ring.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/reconciliation/start","summary":"Open a reconciliation to a statement date and closing balance.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":1500.0,"openingBalance":10005.0},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/reconciliation/{id}","summary":"One session — cleared, uncleared and the difference still to explain.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/reconciliation/{id}/clear/{transactionId}","summary":"Tick a transaction as appearing on the statement.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/unclear/{transactionId}","summary":"Untick it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/clear","summary":"Tick several transactions as appearing on the statement, in one request. All or nothing: a line not on the account, or already reconciled elsewhere, refuses the whole request.","auth":"jwt","body":{"transactionIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/unclear","summary":"Untick several transactions at once.","auth":"jwt","body":{"transactionIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":[],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/finalise","summary":"Close the reconciliation. Refused while the difference is non-zero, and while the books do not tie to the statement.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/reopen","summary":"Reopen a finalised reconciliation.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"OPEN","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/reconciliation/{id}/abandon","summary":"Close an open reconciliation without finalising it, so the account can start a fresh one.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","statementBalance":10005.0,"openingBalance":10005.0,"clearedBalance":10005.0,"difference":1.0,"clearedIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"status":"ABANDONED","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-transactions/{id}/coding-suggestion","auth":"jwt","summary":"How this company coded this payee last time, and how many times in a row — a count, never a confidence.","responseExample":{"category":"Meals & Entertainment","vatRate":0.0,"reason":"OCEAN BASKET — coded this way 4 times.","timesCoded":4,"payeeKey":"ocean basket"},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-transactions/{id}/attachments","auth":"jwt","summary":"The paperwork attached to this statement line.","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"ocean-basket.jpg","caption":null,"contentType":"image/jpeg","sizeBytes":184320,"sequence":1,"uploadedByName":"Thabo Nkosi","fromInboxId":null,"createdAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-transactions/{id}/attachments?filename=till-slip-engen.pdf&contentType=application/pdf&caption=Till%20slip%20for%20the%20fuel","auth":"jwt","summary":"Attach a receipt to this line. Raw bytes, never multipart; the server decides the stored type and the object key.","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"ocean-basket.jpg","contentType":"image/jpeg","sizeBytes":184320,"sequence":1,"createdAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/{id}/attachments/from-inbox","auth":"jwt","summary":"Accept a proposal: link a document the inbox has already filed. No bytes move and no second copy is stored.","bodyExample":{"inboxId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"receipt.pdf","contentType":"application/pdf","sizeBytes":91204,"sequence":2,"fromInboxId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","createdAt":"2026-09-01T09:15:00Z"}],"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"DELETE","path":"/api/bank-transactions/{id}/attachments/{linkId}","auth":"jwt","summary":"Take a file off this line. The file itself is kept — an expense that uses it is untouched.","responseExample":[],"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"GET","path":"/api/bank-transactions/{id}/attachment-proposals","auth":"jwt","summary":"Filed documents of the same amount within a few days of this line. Proposals; nothing is attached.","responseExample":[{"inboxId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"receipt.pdf","supplierName":"Ocean Basket","documentDate":"2026-08-30","amount":1850.0,"daysApart":2,"sentence":"Ocean Basket is for the same amount and is dated 2 days earlier. Attach it to this line?"}],"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-accounts/{accountId}/imports","auth":"jwt","summary":"Every statement read into this account, newest first, and how many lines each still has.","responseExample":{"imports":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"upload","label":"fnb-gold-july-2026.pdf","periodStart":"2026-07-01","periodEnd":"2026-07-31","lineCount":8,"duplicateCount":2,"linesRemaining":8,"importedAt":"2026-09-01T09:15:00Z","importedByName":"Thabo Nkosi"}],"unbatchedLines":14,"unbatchedNote":"Lines imported before Ledgr started recording imports are not grouped into one."},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"GET","path":"/api/bank-imports/{batchId}/undo-preview","auth":"jwt","summary":"What undoing this import would remove, and what it could not — before anything is removed.","responseExample":{"removed":6,"kept":2,"sentence":"Removes 6 lines of the 8 lines this import added. 2 lines stay — 1 is in a finalised reconciliation and 1 is matched to a document.","keptLines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","why":"This line is reconciled."}]},"module":"banking","plan":"Starter","scope":"banking:read"},{"method":"POST","path":"/api/bank-imports/{batchId}/undo","auth":"jwt","summary":"Remove what this import added. Never refuses wholesale, and names every line it could not take.","responseExample":{"removed":6,"kept":2,"sentence":"Removed 6 lines of the 8 lines this import added. 2 lines stay — 1 is in a finalised reconciliation and 1 is matched to a document.","keptLines":[]},"module":"banking","plan":"Starter","scope":"banking:write"},{"method":"POST","path":"/api/bank-transactions/bulk-delete","auth":"jwt","summary":"Remove several ticked statement lines at once, by the same rule the single delete uses.","bodyExample":{"ids":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"removed":1,"kept":0,"sentence":"Removed 1 line of the 1 line this import added.","keptLines":[]},"module":"banking","plan":"Starter","scope":"banking:write"}]},{"name":"General ledger","blurb":"Manual journals, the period lock, cost centres, FX revaluation and the fixed asset register. The roles that may read a trial balance are the roles that may post to it.","endpoints":[{"method":"GET","path":"/api/accounts?type=expense","summary":"The chart of accounts.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","accountType":"asset","accountSubtype":"text","currency":"ZAR","isActive":true,"isSystem":false,"normalBalance":"text","children":[null]}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/accounts","summary":"Add an account.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","accountType":"asset","accountSubtype":"text","currency":"ZAR","isActive":true,"isSystem":false,"normalBalance":"text","children":[null]},"body":{"code":"6340","name":"Delivery Costs","description":"Courier and freight on goods sold","accountType":"expense","accountSubtype":"operating","normalBalance":"debit","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","currency":"ZAR","isSystem":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/accounts/{id}/merge","summary":"Move an account's balance into another of the same type by a journal dated `date`, then retire it. Posted lines are never rewritten; an income or expense account moves this financial year only.","auth":"jwt","body":{"intoAccountId":"7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40","date":"2026-10-31"},"responseExample":{"journalNumber":"JE-2026-000124","moved":300.0},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/accounts/tree","summary":"The chart as a tree, for the picker.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","accountType":"asset","accountSubtype":"text","currency":"ZAR","isActive":true,"isSystem":false,"normalBalance":"text","children":[null]}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/accounts/{id}","summary":"One account with its balance.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","accountType":"asset","accountSubtype":"text","currency":"ZAR","isActive":true,"isSystem":false,"normalBalance":"text","children":[null]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/accounts/{id}","summary":"Rename or recode an account. Setting accountSubtype to investment_in_subsidiary marks a non-current asset account (no other subtype) as the holding company's investment in a subsidiary, which the group balance sheet eliminates; a blank takes that mark off. Any other subtype is stored as given. Setting statementClass (for example other_current on an asset) moves the account to another line of the annual statements and its lead schedule without touching its posting subtype; blank puts it back where the chart classifies it, and cash, bank and register-owned accounts are refused.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","accountType":"asset","accountSubtype":"text","currency":"ZAR","isActive":true,"isSystem":false,"normalBalance":"text","children":[null]},"body":{"name":"Stock write-offs and shrinkage","description":"Consulting services — August 2026","accountSubtype":"operating","isActive":true,"publicBenefitReceipts":false,"pboReceipts":"permissible","pboBearsGeneralCosts":true,"pboExpenditure":"trading","itr14Treatment":"none","statementClass":"other_current"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/accounts/{id}","summary":"Delete an account. Refused while journal lines, invoice lines or quote lines reference it — which is why the Quotes tables survive the route being unmounted.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/journals?from=2026-03-01&to=2027-02-28&sourceType=invoice","summary":"Manual journals.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/journals","summary":"Post a manual journal. Refused unless it balances and the period is open.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false},"body":{"reverseOn":"2026-10-01","journalDate":"2026-08-31","memo":"Depreciation for August","reference":"JNL-0042","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":4166.67,"credit":0.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":0.0,"credit":4166.67,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"post":true,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/journals/{id}","summary":"One journal and its lines.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/journals/{id}/reverse?date=2026-10-01","summary":"Post the contra. Never edits the original.","auth":"jwt","body":{"date":"2026-09-01"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/ledger/journals/{id}/post","summary":"Post a draft journal, under the period lock and balance check a direct post meets. Only a draft is posted.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/ledger/journals/{id}","summary":"Delete a draft journal. A posted journal is reversed, never deleted.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/recurring-journals","summary":"Recurring journals of the active company, each with its lines and newest occurrences.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memo":"text","reference":"INV-0001","frequency":"monthly","startDate":"2026-09-01","endDate":"2026-09-30","nextDate":"2026-09-01","status":"active","totalDebit":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"runs":[{"occurrenceDate":"2026-09-01","outcome":"posted","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","reason":"Budget deferred to the next financial year."}]}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/recurring-journals","summary":"Start a recurring journal. Its lines meet a hand-typed journal's checks; it posts on each occurrence date from startDate.","auth":"jwt","body":{"memo":"Accrue the audit fee","reference":"AUDIT-ACCRUAL","frequency":"monthly","startDate":"2026-11-01","endDate":"2027-02-28","lines":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","debit":4500.0},{"accountId":"7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40","credit":4500.0}],"clientId":"9b3d6e21-4c7a-4f18-a0d5-2e8f1c6b7a94"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memo":"text","reference":"INV-0001","frequency":"monthly","startDate":"2026-09-01","endDate":"2026-09-30","nextDate":"2026-09-01","status":"active","totalDebit":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"runs":[{"occurrenceDate":"2026-09-01","outcome":"posted","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","reason":"Budget deferred to the next financial year."}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/ledger/recurring-journals/{id}/status","summary":"Pause, resume or end a recurring journal. A resumed one picks up at its next date on or after today.","auth":"jwt","body":{"status":"paused"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memo":"text","reference":"INV-0001","frequency":"monthly","startDate":"2026-09-01","endDate":"2026-09-30","nextDate":"2026-09-01","status":"active","totalDebit":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis2Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","analysis3Id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"runs":[{"occurrenceDate":"2026-09-01","outcome":"posted","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","reason":"Budget deferred to the next financial year."}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/books-open","summary":"The day after the opening balances, or null when there are none. A journal dated before it posts, with a notice.","auth":"jwt","responseExample":{"date":"2026-11-01"},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/ledger/journal-batches","summary":"Journal batches of the active company, open ones first.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"October payroll","reference":"BUR-10","status":"open","lineCount":24,"totalDebit":185000.0,"totalCredit":185000.0,"lines":[],"journals":[],"createdAt":"2026-09-01T09:15:00Z"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/journal-batches","summary":"Keep a worksheet of journal lines. Unfinished lines are allowed; only posting judges them.","auth":"jwt","body":{"name":"October payroll","reference":"BUR-10","lines":[{"journalDate":"2026-10-31","accountCode":"6200","description":"Gross salaries","debit":185000.0},{"journalDate":"2026-10-31","accountCode":"2150","credit":185000.0}],"clientId":"9b3d6e21-4c7a-4f18-a0d5-2e8f1c6b7a94"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"October payroll","reference":"BUR-10","status":"open","lineCount":2,"totalDebit":185000.0,"totalCredit":185000.0,"lines":[{"journalDate":"2026-10-31","accountCode":"6200","description":"Gross salaries","debit":185000.0,"credit":0.0}],"journals":[]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/journal-batches/{id}","summary":"A batch with its lines, and the journals it posted once it has.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"October payroll","status":"posted","lineCount":2,"totalDebit":185000.0,"totalCredit":185000.0,"lines":[],"journals":[{"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"JE-2026-000120","journalDate":"2026-10-31","total":185000.0}],"postedAt":"2026-11-01T09:15:00Z"},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/ledger/journal-batches/{id}","summary":"Replace an open batch's name and lines. A posted batch cannot be changed.","auth":"jwt","body":{"name":"October payroll","reference":"BUR-10","clientId":"9b3d6e21-4c7a-4f18-a0d5-2e8f1c6b7a94","lines":[{"journalDate":"2026-10-31","accountCode":"6200","debit":185000.0},{"journalDate":"2026-10-31","accountCode":"2150","credit":185000.0}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"October payroll","status":"open","lineCount":2,"totalDebit":185000.0,"totalCredit":185000.0,"lines":[],"journals":[]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/ledger/journal-batches/{id}/post","summary":"Post a batch as one journal per date, all of them or none. Each date must balance. Posting a posted batch moves nothing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"October payroll","status":"posted","lineCount":2,"totalDebit":185000.0,"totalCredit":185000.0,"lines":[],"journals":[{"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"JE-2026-000120","journalDate":"2026-10-31","total":185000.0}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/ledger/journal-batches/{id}","summary":"Throw an open batch away. Nothing reached the ledger, so nothing is undone.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/bills/{id}/seller-declaration?filename=vat264.pdf&contentType=application/pdf&signedOn=2026-09-01","summary":"Keep the second-hand seller's signed declaration (VAT264) on the bill: the raw bytes as the body, the name and the day it was signed in the query. Notional input tax on the bill's second-hand lines is claimed only while it is held.","auth":"jwt","responseExample":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sellerDeclarationUrl":"/api/files/7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40","sellerDeclarationSignedOn":"2026-09-01"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/bills/{id}/seller-declaration","summary":"Take the seller's declaration off a bill. The file is kept; the notional input tax it substantiated is taken back.","auth":"jwt","responseExample":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sellerDeclarationUrl":null,"sellerDeclarationSignedOn":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/ledger/journals/{id}/attachments","summary":"The working papers on a journal.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40","filename":"working-paper.pdf","contentType":"application/pdf","sizeBytes":20480}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/journals/{id}/attachments?filename=working-paper.pdf&contentType=application/pdf","summary":"Attach a file to a journal: the raw bytes as the body, the name in the query. A posted journal takes files too.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40","filename":"working-paper.pdf","contentType":"application/pdf","sizeBytes":20480}],"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/ledger/journals/{id}/attachments/{linkId}","summary":"Take a file off a journal. The file is kept.","auth":"jwt","responseExample":[],"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/budget-scenarios","summary":"The named budgets this company holds. `Main` is always among them.","auth":"jwt","responseExample":["Bank","Main"],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/account-budgets/seed","summary":"Fill a named budget from last year's actuals, month for month, lifted by a percentage. Seeding again replaces.","auth":"jwt","body":{"scenario":"Bank","yearStart":"2026-03-01","upliftPercent":10.0},"responseExample":{"saved":48},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/periods","summary":"Accounting periods and their lock state.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","label":"Karoo Fresh Holdings Ltd","status":"sent","closedAt":"2026-09-01T09:15:00Z"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/periods","summary":"Open a period.","auth":"jwt","body":{"periodStart":"2026-09-01","periodEnd":"2026-09-30","label":"September 2026"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","label":"Karoo Fresh Holdings Ltd","status":"sent","closedAt":"2026-09-01T09:15:00Z"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/ledger/periods/{id}/status","summary":"Lock or unlock a period. A locked period refuses every posting, including automatic ones.","auth":"jwt","body":{"status":"locked"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","label":"Karoo Fresh Holdings Ltd","status":"sent","closedAt":"2026-09-01T09:15:00Z","reviewedAt":"2026-09-01T09:15:00Z","reviewedBy":"Karoo Fresh Holdings Ltd","closedByFirm":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/ledger/periods/{id}/review","summary":"A reviewer signs a closed or locked period off. Needs reports:approve; the person who closed it does not review it while somebody else can. Reopening the period takes the sign-off off.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","label":"Karoo Fresh Holdings Ltd","status":"sent","closedAt":"2026-09-01T09:15:00Z","reviewedAt":"2026-09-01T09:15:00Z","reviewedBy":"Karoo Fresh Holdings Ltd","closedByFirm":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/journal-approval-policy","summary":"The amount from which a hand-typed journal is posted by a second person who can approve, not by the person who made it. Null: one person posts at every amount.","auth":"jwt","responseExample":{"secondApprovalFrom":1.0,"approvers":1,"mayChange":false,"summary":"Consulting services — August 2026"},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/ledger/journal-approval-policy","summary":"Set the amount from which a manual journal needs a second person to post it, or turn it off with null. The owner or an admin who can approve reports.","auth":"jwt","body":{"secondApprovalFrom":10000.0},"responseExample":{"secondApprovalFrom":1.0,"approvers":1,"mayChange":false,"summary":"Consulting services — August 2026"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/cost-centres?dimension=1","summary":"Cost centres — or, with dimension=2 or 3, the values of the tenant's second or third analysis dimension.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/cost-centres","summary":"Add a cost centre.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true},"body":{"code":"CPT","name":"Cape Town branch","description":"Consulting services — August 2026","kind":"department","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"dimension":1,"restricted":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/analysis-dimensions","summary":"The company's three analysis dimensions and their names. Dimension 1 is the cost centre and always on; 2 and 3 (a project, a fund) are on once named. A dimension's values are cost centres created with that dimension, listed by GET /api/ledger/cost-centres?dimension=2.","auth":"jwt","responseExample":[{"slot":1,"name":"Cost centre","enabled":true},{"slot":2,"name":"Project","enabled":true},{"slot":3,"name":"Dimension 3","enabled":false}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/ledger/analysis-dimensions","summary":"Name dimensions 2 and 3. A blank name switches the dimension off for new documents; postings already tagged keep their values and still report.","auth":"jwt","responseExample":[{"slot":1,"name":"Cost centre","enabled":true},{"slot":2,"name":"Project","enabled":true},{"slot":3,"name":"Fund","enabled":true}],"body":{"dimension2":"Project","dimension3":"Fund"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/ledger/cost-centres/{id}","summary":"Rename a cost centre.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true},"body":{"code":"CPT","name":"Cape Town Depot","description":"Consulting services — August 2026","kind":"branch","parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true,"restricted":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/ledger/cost-centres/{id}","summary":"Remove a cost centre.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/account-budgets?from=2026-03-01&to=2027-02-28&scenario=Main","summary":"Budgets per ledger account and period.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","accountType":"asset","periodMonth":"2026-09-01","amount":10005.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","notes":"Budget deferred to the next financial year."}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/ledger/account-budgets","summary":"Set a budget line.","auth":"jwt","responseExample":{"saved":1},"body":{"budgets":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodMonth":"2026-09-01","amount":45000.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Approved at the August board meeting"}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/ledger/account-budgets/{id}","summary":"Remove a budget line.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/budget-by-account?to=2027-02-28&from=2026-03-01&scenario=Main","summary":"Budget against actual, by account.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","periodLabel":"2026-09","revenue":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","budget":1.0,"actual":1.0,"variance":1.0,"variancePct":1.0}],"costOfSales":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","budget":1.0,"actual":1.0,"variance":1.0,"variancePct":1.0}],"expenses":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","budget":1.0,"actual":1.0,"variance":1.0,"variancePct":1.0}],"totalBudgetedRevenue":10005.0,"totalActualRevenue":10005.0,"totalBudgetedCost":10005.0,"totalActualCost":10005.0,"budgetedProfit":1.0,"actualProfit":1.0,"empty":true},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/ledger/fx-revaluations","summary":"Period-end FX revaluations already posted.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodEnd":"2026-09-30","baseCurrency":"ZAR","netAdjustment":8700.0,"documentsRevalued":1,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","currency":"ZAR","outstanding":1.0,"bookedRate":15.0,"closingRate":15.0,"bookedBase":1.0,"restatedBase":1.0,"adjustment":1.0}],"missingRates":["text"]}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/fx-revaluation?periodEnd=2027-02-28","summary":"Revalue foreign-currency balances (invoices, credit notes, customers' kept credit, bills and foreign bank accounts) at the closing rate and post the difference. The closing rate is the newest rate on or before the period end, a rate typed for that very day first; an older typed rate is not carried forward past a newer published one (IFRS for SMEs 30.9).","auth":"jwt","body":{"asOf":"2026-08-31"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodEnd":"2026-09-30","baseCurrency":"ZAR","netAdjustment":8700.0,"documentsRevalued":1,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lines":[{"sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","currency":"ZAR","outstanding":1.0,"bookedRate":15.0,"closingRate":15.0,"bookedBase":1.0,"restatedBase":1.0,"adjustment":1.0}],"missingRates":["text"]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/health","summary":"Control-account checks — each control account against the record that explains it, as at today: 1320 against aged debtors, 2110 against aged creditors, 1310 against the stock valuation, the VAT accounts against what SARS is owed, 2140–2142 against the EMP201s and payslips, 1315 work in progress against open work orders and job-card parts, the fixed asset cost and accumulated depreciation against the asset register, each bank account with a statement against its closing balance, each loan account and 2121 against the loan register, and 2115 GRNI against the goods received and not yet invoiced. The year-end checklist strikes the same ties as at the year end.","auth":"jwt","responseExample":{"journals":1,"posted":1,"reversed":1,"draft":1,"unbalancedJournals":1,"chartAccounts":3,"chartSeeded":true},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/ledger/rebuild","summary":"Rebuild the ledger from source documents. The repair of last resort, not a routine.","auth":"jwt","responseExample":{"invoices":1,"payments":1,"bills":1,"billPayments":1,"expenses":1,"payrollRuns":1,"journalsPosted":1,"failures":[]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/ledger/seed-chart","summary":"Seed a standard SA chart of accounts into an empty tenant.","auth":"jwt","responseExample":{"accountsCreated":3},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/fx/rates?base=ZAR&asOf=2026-09-30","summary":"Exchange rates held, and how old each one is; with asOf, the rates a document dated that day converts at.","auth":"jwt","responseExample":{"baseCurrency":"ZAR","rates":[{"fromCurrency":"ZAR","toCurrency":"ZAR","rate":15.0,"asOf":"text","source":"referral","fetchedAt":"2026-09-01T09:15:00Z","stale":false}],"anyStale":false,"summary":"Consulting services — August 2026"}},{"method":"PUT","path":"/api/fx/rates","summary":"Record a rate by hand.","auth":"jwt","responseExample":{"baseCurrency":"ZAR","rates":[{"fromCurrency":"ZAR","toCurrency":"ZAR","rate":15.0,"asOf":"text","source":"referral","fetchedAt":"2026-09-01T09:15:00Z","stale":false}],"anyStale":false,"summary":"Consulting services — August 2026"},"body":{"fromCurrency":"ZAR","toCurrency":"ZAR","rate":15.0,"asOf":"2026-09-30"}},{"method":"DELETE","path":"/api/fx/rates/{from}","summary":"Put one currency back on the published rate, clearing what was entered by hand.","auth":"jwt","responseExample":{"cleared":true,"message":"EUR is back on the published rate. Refresh to fetch today's.","rates":{"baseCurrency":"ZAR","rates":[{"fromCurrency":"EUR","toCurrency":"ZAR","rate":19.74,"asOf":"2026-09-19","source":"ecb","fetchedAt":"2026-09-19T09:15:00Z","stale":false}],"anyStale":false,"summary":"Consulting services — August 2026"}}},{"method":"POST","path":"/api/fx/refresh","summary":"Fetch the latest rates from the ECB.","auth":"jwt","responseExample":{"ok":true,"source":"referral","asOf":"text","inserted":1,"updated":1,"skippedManual":1,"currencies":["text"],"fromCache":false,"fetchedMinutesAgo":1,"failureReason":"Budget deferred to the next financial year."}},{"method":"GET","path":"/api/fixed-assets?includeDisposed=true","summary":"The asset register.","auth":"jwt","responseExample":{"asOf":"text","assets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1}],"totalCost":10005.0,"totalAccumulatedDepreciation":10005.0,"totalBookValue":10005.0,"byClass":[{"assetClass":"text","label":"Karoo Fresh Holdings Ltd","count":3,"cost":10005.0,"accumulatedDepreciation":1.0,"bookValue":10005.0}],"periodsOutstanding":1},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/fixed-assets","summary":"Capitalise an asset against a SARS BGR7 class, with the income tax allowance it is claimed under (taxAllowance), any tax value brought in, and the date it was brought into use (broughtIntoUseDate, not before the purchase; the allowance runs from it, the purchase date when blank).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1},"body":{"name":"Karoo Fresh Holdings Ltd","assetClass":"Computer equipment","acquisitionDate":"2026-09-30","cost":1500.0,"description":"Consulting services — August 2026","residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"serialNumber":"INV-0001","location":"Cape Town HQ","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capitalise":true,"reclassifyFromAccountCode":"CT-001","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vatAmount":225.0,"supplierVatNumber":"4082456789","passengerCar":false,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","taxAllowance":"s12e","taxValue":30000.0,"taxValueDate":"2026-02-28","broughtIntoUseDate":"2026-03-15"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/fixed-assets/classes","summary":"The SARS BGR7 wear-and-tear classes and their write-off periods.","auth":"jwt","responseExample":[{"key":"text","label":"Karoo Fresh Holdings Ltd","defaultLifeMonths":1,"defaultMethod":"eft","depreciable":true,"note":"Budget deferred to the next financial year."}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/fixed-assets/capitalisation-policy","summary":"The company's capitalisation threshold (items under it are expensed) and SARS's R7 000 small item limit.","auth":"jwt","responseExample":{"threshold":5000.0,"smallItemLimit":7000.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/fixed-assets/capitalisation-policy","summary":"Set the company's capitalisation threshold, or clear it with null.","auth":"jwt","responseExample":{"threshold":5000.0,"smallItemLimit":7000.0},"body":{"threshold":5000.0},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/fixed-assets/capitalisation-check?accountCode=1140&amount=3000","summary":"Read where a purchase is coded: does the capitalisation policy suggest another account for this amount? It suggests and never decides.","auth":"jwt","responseExample":{"advice":"This is under your capitalisation policy of R5000.00, so an item like it is normally expensed, not capitalised. Code it to 6050 Computer & IT Expenses instead of 1140, or lower the policy.","suggestedAccountCode":"6050"},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/fixed-assets/{id}","summary":"One asset with its carrying value.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/fixed-assets/{id}","summary":"Update an asset.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1},"body":{"name":"Toyota Hilux (CA 123-456)","description":"Consulting services — August 2026","residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"serialNumber":"INV-0001","location":"Cape Town HQ","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","taxAllowance":"s12e","taxValue":30000.0,"taxValueDate":"2026-02-28","broughtIntoUseDate":"2026-03-15"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/fixed-assets/{id}","summary":"Remove an asset that was capitalised in error.","auth":"jwt","responseExample":{"ledgerNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/fixed-assets/{id}/schedule","summary":"The depreciation schedule for one asset.","auth":"jwt","responseExample":[{"periodEnd":"2026-09-30","amount":10005.0,"accumulatedAfter":1.0,"bookValueAfter":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/fixed-assets/depreciation/run?through=2027-02-28","summary":"Post the month's depreciation across the register.","auth":"jwt","body":{"period":"2026-08"},"responseExample":{"assetsProcessed":1,"periodsPosted":1,"totalCharged":10005.0,"skipped":["text"]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/fixed-assets/{id}/dispose","summary":"Dispose of an asset and post the profit or loss.","auth":"jwt","body":{"disposalDate":"2026-09-30","proceeds":310000.0,"bankAccountId":"7f6c1a2e-0000-4000-8000-000000000001","inputTaxWasDenied":false,"customerId":null},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1},"module":"reports","plan":"Business","scope":"reports:write"}]},{"name":"Reports & analytics","blurb":"IFRS-for-SMEs statements, management reports and the compliance set. /api/reports/summary and /api/reports/cash-forecast belong to the DASHBOARD module, not REPORTS, so a Free tenant's dashboard is not blank.","endpoints":[{"method":"GET","path":"/api/reports/summary","summary":"The dashboard KPI row — cash, receivables, revenue MTD.","auth":"jwt","responseExample":{"ytdRevenue":1.0,"netProfit":8700.0,"totalAssets":10005.0,"outstanding":1.0,"bbbeeScored":1,"bbbeeMax":1,"bbbeeLevel":1,"grossMarginPct":1,"netMarginPct":1,"periodLabel":"2026-09","monthlyTrend":[{"month":"2026-09","revenue":1.0,"expenses":1.0,"cogs":1.0,"outputVat":1305.0}],"cash":{"asOfLabel":"Karoo Fresh Holdings Ltd","ledgerBalance":10005.0,"cashAtBank":1.0,"overdrafts":1.0,"statementBalance":10005.0,"unreconciledDifference":1.0}},"module":"dashboard","plan":"Free","scope":"dashboard:read"},{"method":"GET","path":"/api/reports/kpi-summary","summary":"The same KPI figures for the Reports screen — needs reports:view only (the dashboard's /api/reports/summary also needs dashboard:view).","auth":"jwt","responseExample":{"ytdRevenue":1.0,"netProfit":8700.0,"totalAssets":10005.0,"outstanding":1.0,"bbbeeScored":1,"bbbeeMax":1,"bbbeeLevel":1,"grossMarginPct":1,"netMarginPct":1,"periodLabel":"2026-09","monthlyTrend":[{"month":"2026-09","revenue":1.0,"expenses":1.0,"cogs":1.0,"outputVat":1305.0}],"cash":{"asOfLabel":"Karoo Fresh Holdings Ltd","ledgerBalance":10005.0,"cashAtBank":1.0,"overdrafts":1.0,"statementBalance":10005.0,"unreconciledDifference":1.0}},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/cash-forecast?days=90","summary":"The cash runway ring's figures.","auth":"jwt","responseExample":{"asOfLabel":"Karoo Fresh Holdings Ltd","openingBalance":10005.0,"weeks":[{"label":"Karoo Fresh Holdings Ltd","inflow":1.0,"outflow":1.0,"balance":10005.0}],"statementBalance":10005.0,"unreconciledDifference":1.0,"overdueReceivables":1.0},"module":"dashboard","plan":"Free","scope":"dashboard:read"},{"method":"GET","path":"/api/reports/income-statement?from=2026-03-01&to=2027-02-28&compare=previous-year&columns=quarter","summary":"Income statement (IFRS for SMEs).","auth":"jwt","responseExample":{"periodLabel":"2026-09","revenue":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"costOfSales":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"operatingExpenses":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"otherIncome":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"tax":1305.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/balance-sheet?from=2026-03-01&asOf=2027-02-28&compare=previous-year&columns=quarter","summary":"Balance sheet at a date.","auth":"jwt","responseExample":{"asOfLabel":"Karoo Fresh Holdings Ltd","currentAssets":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"nonCurrentAssets":[{"name":"Karoo Fresh Holdings Ltd","cost":10005.0,"accumulatedDepreciation":1.0}],"currentLiabilities":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"nonCurrentLiabilities":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"shareCapital":1.0,"retainedEarnings":1.0,"currentYearProfit":1.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/cash-flow?from=2026-03-01&to=2027-02-28&compare=previous-year&columns=quarter","summary":"Direct-method cash flow statement.","auth":"jwt","responseExample":{"periodLabel":"2026-09","operating":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"investing":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"financing":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"cashAtStart":1.0,"cashAtEnd":1.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/report-packs","summary":"Management packs: a cover, commentary and an ordered list of reports produced for one period (last_month or year_to_date).","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Board pack","coverTitle":"Monthly board pack","commentary":"A strong month.","reports":["income","balance","ageddebtors"],"period":"last_month"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/report-packs","summary":"Save a management pack. Every report must be one a schedule can send; an unknown one is refused, not dropped.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Board pack","coverTitle":"Monthly board pack","commentary":"A strong month.","reports":["income","balance","ageddebtors"],"period":"last_month"},"body":{"name":"Board pack","coverTitle":"Monthly board pack","commentary":"A strong month.","reports":["income","balance","ageddebtors"],"period":"last_month"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/report-packs/{id}","summary":"Change a management pack.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Board pack","coverTitle":"Monthly board pack","commentary":"A strong month.","reports":["income","balance","ageddebtors"],"period":"last_month"},"body":{"name":"Board pack","coverTitle":"Monthly board pack","commentary":"A strong month.","reports":["income","balance","ageddebtors"],"period":"last_month"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/report-packs/{id}","summary":"Remove a management pack.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/report-packs/{id}/pdf?from=2026-09-01&to=2026-09-30","summary":"The pack as one PDF: the cover and commentary, then each report on its own page, built by the same code as the report on the screen. Without from and to it is the pack's own period.","auth":"jwt","responseKind":"pdf","module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/favourites","summary":"The signed-in user's favourite reports, in their gallery order.","auth":"jwt","responseExample":{"reportIds":["ratios","income"]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/reports/favourites","summary":"Replace the signed-in user's favourite reports, in order.","auth":"jwt","responseExample":{"reportIds":["ratios","income"]},"body":{"reportIds":["ratios","income"]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/recurring/{id}/lease","summary":"A recurring schedule's lease terms: property (a value of an analysis dimension), unit, start, escalation and the deposit the agreement requires (what is actually held is on /deposit). The rent, tenant, cycle and end date are the schedule's. 404 when the schedule has no lease.","auth":"jwt","responseExample":{"id":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","scheduleId":"a3c4d5e6-f7a8-4b9c-8d0e-1f2a3b4c5d6e","propertyId":"7d0c2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","propertyName":"12 Main Street","unit":"1A","startDate":"2026-03-01","endDate":"2029-02-28","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","contactName":"Unit Tenant","rent":10800.0,"frequency":"monthly","escalationPercent":8.0,"escalationDate":"2027-03-01","escalationMonths":12,"nextRent":11664.0,"deposit":20000.0},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"PUT","path":"/api/recurring/{id}/lease","summary":"Create or replace a schedule's lease terms. An escalation needs the date it first applies; the cycle raised on or after that date is raised at the escalated rent, and the date then moves on by escalationMonths. use is residential (the rent is raised VAT exempt) or commercial. straightLine true recognises the rent on a straight line over the term (IFRS for SMEs 20.25): the schedule must have an end date, the level rent is fixed from the cycles still to come, each rent invoice then credits income at the level rent and carries the difference to 1335 Straight-line Rent Receivable, and the last invoice clears it. It cannot be switched off once an invoice has been raised under it.","auth":"jwt","body":{"propertyId":"7d0c2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","unit":"1A","startDate":"2026-03-01","escalationPercent":8.0,"escalationDate":"2027-03-01","escalationMonths":12,"deposit":20000.0,"use":"residential","straightLine":true},"responseExample":{"id":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","scheduleId":"a3c4d5e6-f7a8-4b9c-8d0e-1f2a3b4c5d6e","propertyId":"7d0c2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","propertyName":"12 Main Street","unit":"1A","startDate":"2026-03-01","endDate":"2029-02-28","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","contactName":"Unit Tenant","rent":10800.0,"frequency":"monthly","escalationPercent":8.0,"escalationDate":"2027-03-01","escalationMonths":12,"nextRent":11664.0,"deposit":20000.0},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"DELETE","path":"/api/recurring/{id}/lease","summary":"Remove a schedule's lease terms. The schedule itself, and the invoices it has raised, are untouched.","auth":"jwt","responseKind":"none","module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/rented-leases","summary":"The leases the business rents (IFRS for SMEs 20.15): landlord, term, the first cycle's rent excluding VAT, its escalation, the level expense per cycle those make, and what the bills against each lease have billed, expensed and accrued so far (the accrual is account 2122 Straight-line Rent Accrual).","auth":"jwt","responseExample":[{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","contactName":"Karoo Properties","description":"Head office, 12 Main Street","startDate":"2026-03-01","endDate":"2029-02-28","intervalMonths":1,"rent":10000.0,"escalationPercent":10.0,"escalationDate":"2027-03-01","escalationMonths":12,"levelRent":11033.33,"cycles":36,"bills":12,"billed":120000.0,"expensed":132399.96,"accrued":12399.96,"kind":"operating","loanId":null,"fixedAssetId":null}],"module":"expenses","plan":"Starter","scope":"expenses:read"},{"method":"POST","path":"/api/rented-leases","summary":"Make a lease the business rents. Its rent expense is straight-lined over the term: a bill that names the lease (rentedLeaseId on POST/PUT /api/bills) is expensed at the level amount and the difference goes to 2122 Straight-line Rent Accrual, which the last bill clears. The term needs an end date; escalation needs the date it first applies; rent falls due every 1, 3, 6 or 12 months. 400 names what to correct.","auth":"jwt","body":{"contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","description":"Head office, 12 Main Street","startDate":"2026-03-01","endDate":"2029-02-28","intervalMonths":1,"rent":10000.0,"escalationPercent":10.0,"escalationDate":"2027-03-01","escalationMonths":12},"responseExample":{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","contactName":"Karoo Properties","description":"Head office, 12 Main Street","startDate":"2026-03-01","endDate":"2029-02-28","intervalMonths":1,"rent":10000.0,"escalationPercent":10.0,"escalationDate":"2027-03-01","escalationMonths":12,"levelRent":11033.33,"cycles":36,"bills":12,"billed":120000.0,"expensed":132399.96,"accrued":12399.96,"kind":"operating","loanId":null,"fixedAssetId":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"POST","path":"/api/rented-leases/finance","summary":"Record a lease the business holds as a FINANCE lease (IFRS for SMEs 20.9-20.12): monthly payments in arrears (or, with paymentsInAdvance, the first on startDate), the rate implicit in the lease (or the incremental borrowing rate) and the item's fair value. The asset and the obligation are recognised at the lower of the fair value and the payments' present value: the obligation is a borrowing in the loan register (its schedule splits each payment into finance charge and capital, and the balance sheet splits it current and non-current), the asset an entry in the fixed asset register depreciated over the shorter of the lease term and its useful life unless ownership is expected, and the journal DR the asset class's cost account / CR the obligation account (2020 by default). initialDirectCosts are added to the asset (20.9); a payment in advance is settled at once, so the obligation is the rest; both leave the bank account bankAccountId as its own bank leg (with none named, the company's only bank account, or the pooled 1350 when it has none; several and none named is refused), or are credited to paidFromAccountCode when it names another account. assetCost and obligation answer what was recognised. The statements note the carrying amount of the assets held under finance leases by class (20.13(a)). Code each later payment as a loan instalment. 400 names what to correct.","auth":"jwt","body":{"contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","lessorName":"WesBank","description":"Delivery vehicle","startDate":"2026-03-01","payment":5000.0,"payments":36,"ratePercent":12.0,"fairValue":160000.0,"assetClass":"motor_vehicle","usefulLifeMonths":60,"ownershipExpected":false,"obligationAccountCode":"2020","paymentsInAdvance":false,"initialDirectCosts":2000.0,"paidFromAccountCode":"1350","bankAccountId":"5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e"},"responseExample":{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","loanId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","assetNumber":"FA-0007","description":"Delivery vehicle","lessorName":"WesBank","startDate":"2026-03-01","endDate":"2029-03-01","payment":5000.0,"payments":36,"ratePercent":12.0,"fairValue":160000.0,"presentValue":150537.53,"carryingAmount":150537.53,"effectiveRatePercent":12.0,"depreciationMonths":36,"obligationAccountCode":"2020","assetAccountCode":"1120","paymentsInAdvance":false,"initialDirectCosts":2000.0,"assetCost":152537.53,"obligation":150537.53},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/rented-leases/{id}","summary":"Change a lease the business rents. The landlord and description can change at any time; the term, rent and escalation cannot once a bill is against the lease (409 names the remedy: take the bills off it, or make a new lease).","auth":"jwt","body":{"contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","description":"Head office, 12 Main Street","startDate":"2026-03-01","endDate":"2029-02-28","intervalMonths":1,"rent":10000.0,"escalationPercent":10.0,"escalationDate":"2027-03-01","escalationMonths":12},"responseExample":{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","contactName":"Karoo Properties","description":"Head office, 12 Main Street","startDate":"2026-03-01","endDate":"2029-02-28","intervalMonths":1,"rent":10000.0,"escalationPercent":10.0,"escalationDate":"2027-03-01","escalationMonths":12,"levelRent":11033.33,"cycles":36,"bills":12,"billed":120000.0,"expensed":132399.96,"accrued":12399.96,"kind":"operating","loanId":null,"fixedAssetId":null},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"DELETE","path":"/api/rented-leases/{id}","summary":"Remove a lease the business rents. 409 while bills are against it: its straight-line accrual would be stranded; clear the lease on each bill first.","auth":"jwt","responseKind":"none","module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/recurring/{id}/lease/deposit","summary":"A lease's deposit: what the agreement requires, what the lease HOLDS (taken less applied less refunded — the book that ties to account 2158 Tenant Deposits Held), and every movement.","auth":"jwt","responseExample":{"leaseId":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","required":20000.0,"held":18000.0,"movements":[{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","kind":"taken","amount":20000.0,"on":"2026-03-01","method":"eft","reference":"Deposit 1A","journalId":"3f2e1d0c-9b8a-4766-8554-433221100ffe"},{"id":"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e","kind":"applied","amount":2000.0,"on":"2026-09-30","invoiceId":"d4c3b2a1-0f9e-4d8c-8b7a-695847362514"}]},"module":"invoices","plan":"Free","scope":"invoices:read"},{"method":"POST","path":"/api/recurring/{id}/lease/deposit","summary":"Take the tenant's deposit: debits the bank account and credits 2158 Tenant Deposits Held (a liability, tagged with the tenant, no VAT). With interest true it records the bank's interest on the deposit account instead — the tenant's (Rental Housing Act s5(3)), booked the same way as a movement of kind interest, held and refunded with the deposit, never income. The rent roll's deposit held reads this book. A bank line cannot be coded straight to 2158.","auth":"jwt","body":{"amount":20000.0,"bankAccountId":"6e5d4c3b-2a19-4807-96f5-e4d3c2b1a098","on":"2026-03-01","method":"eft","reference":"Deposit 1A","interest":false},"responseExample":{"leaseId":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","required":20000.0,"held":18000.0,"movements":[{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","kind":"taken","amount":20000.0,"on":"2026-03-01","method":"eft","reference":"Deposit 1A","journalId":"3f2e1d0c-9b8a-4766-8554-433221100ffe"},{"id":"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e","kind":"applied","amount":2000.0,"on":"2026-09-30","invoiceId":"d4c3b2a1-0f9e-4d8c-8b7a-695847362514"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/recurring/{id}/lease/deposit/apply","summary":"Apply the deposit held to one of the tenant's own invoices, up to what it owes, as a payment out of 2158 (DR 2158 / CR 1320). Whatever is left stays held for a refund. 409 when the lease holds nothing or the invoice is another customer's.","auth":"jwt","body":{"invoiceId":"d4c3b2a1-0f9e-4d8c-8b7a-695847362514","on":"2026-09-30"},"responseExample":{"leaseId":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","required":20000.0,"held":18000.0,"movements":[{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","kind":"taken","amount":20000.0,"on":"2026-03-01","method":"eft","reference":"Deposit 1A","journalId":"3f2e1d0c-9b8a-4766-8554-433221100ffe"},{"id":"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e","kind":"applied","amount":2000.0,"on":"2026-09-30","invoiceId":"d4c3b2a1-0f9e-4d8c-8b7a-695847362514"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"POST","path":"/api/recurring/{id}/lease/deposit/refund","summary":"Pay back the deposit held — all of it, or amount — from a bank account (DR 2158 / CR bank). 409 when more than is held is asked for.","auth":"jwt","body":{"bankAccountId":"6e5d4c3b-2a19-4807-96f5-e4d3c2b1a098","on":"2026-09-30","amount":3000.0,"reference":"Refund 1A"},"responseExample":{"leaseId":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","required":20000.0,"held":18000.0,"movements":[{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","kind":"taken","amount":20000.0,"on":"2026-03-01","method":"eft","reference":"Deposit 1A","journalId":"3f2e1d0c-9b8a-4766-8554-433221100ffe"},{"id":"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e","kind":"applied","amount":2000.0,"on":"2026-09-30","invoiceId":"d4c3b2a1-0f9e-4d8c-8b7a-695847362514"}]},"module":"invoices","plan":"Free","scope":"invoices:write"},{"method":"GET","path":"/api/reports/rent-roll?asOf=2026-10-13","summary":"Every lease: property, unit, tenant, rent, next escalation and the rent it brings, the deposit the agreement requires and the deposit HELD (the lease's deposit book, which ties to account 2158 Tenant Deposits Held; the roll shows the ledger's 2158 and the difference), and what the tenant owes and how much of it is past due at the date — the same receivables the aged debtors report reads, per tenant. Only leases running on the date are listed; rents are totalled as monthly equivalents of base-currency leases, and the owed and arrears totals count each tenant once.","auth":"jwt","responseExample":{"asOf":"2026-10-13","rows":[{"leaseId":"5b1e9c3a-7d2f-4e8a-9c10-2f3a4b5c6d7e","scheduleId":"a3c4d5e6-f7a8-4b9c-8d0e-1f2a3b4c5d6e","property":"12 Main Street","unit":"1A","contactId":"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f","tenantName":"Unit Tenant","rent":10800.0,"frequency":"monthly","currency":"ZAR","monthlyRent":10800.0,"active":true,"startDate":"2026-03-01","endDate":"2029-02-28","nextEscalation":"2027-03-01","nextRent":11664.0,"deposit":20000.0,"depositHeld":20000.0,"owed":15800.0,"arrears":5000.0}],"totalMonthlyRent":10800.0,"foreignCurrencyLeases":0,"totalDeposits":20000.0,"depositsLedgerBalance":20000.0,"depositsDifference":0.0,"totalOwed":15800.0,"totalArrears":5000.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/funds?from=2026-03-01&to=2027-02-28&dimension=2","summary":"A non-profit's funds: each value of the fund dimension with its balance brought forward, income, expenditure and balance carried forward, restricted funds marked. The figures are the departmental income statement's on that dimension; totalSurplus is checked against the income statement and reconciles says whether they agree.","auth":"jwt","responseExample":{"periodLabel":"1 March 2026 – 28 February 2027","from":"2026-03-01","to":"2027-02-28","dimension":2,"dimensionName":"Fund","funds":[{"fundId":"7d0c2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","code":"BUILD","name":"Building fund","restricted":true,"opening":40000.0,"income":25000.0,"expenditure":18000.0,"surplus":7000.0,"closing":47000.0}],"totalSurplus":7000.0,"incomeStatementSurplus":7000.0,"reconciles":true,"restrictedClosing":47000.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/funds/{fundId}?from=2026-03-01&to=2027-02-28&dimension=2","summary":"The report a donor receives for one fund: its movement for the period and the income statement lines behind it.","auth":"jwt","responseExample":{"periodLabel":"1 March 2026 – 28 February 2027","fund":{"fundId":"7d0c2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","code":"BUILD","name":"Building fund","restricted":true,"opening":40000.0,"income":25000.0,"expenditure":18000.0,"surplus":7000.0,"closing":47000.0},"statement":{"periodLabel":"1 March 2026 – 28 February 2027","revenue":[],"costOfSales":[],"operatingExpenses":[],"otherIncome":[],"tax":0.0}},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/ratios?from=2026-03-01&to=2027-02-28","summary":"Current and quick ratio, debtor, creditor and stock days, gross and net margin for the period, at its last day. Each ratio carries the two figures it divides, read from the statement that owns them; a ratio whose denominator is zero is null rather than 0.","auth":"jwt","responseExample":{"periodLabel":"1 March 2026 – 28 February 2027","from":"2026-03-01","to":"2027-02-28","days":365,"ratios":[{"key":"debtorDays","label":"Debtor days","unit":"days","value":41.2,"numerator":125000.0,"denominator":1107400.0,"formula":"Receivables ÷ credit sales × days in the period"}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/trial-balance?asOf=2027-02-28&from=2026-03-01&to=2027-02-28&includeZero=true&compare=previous-year&costCentreId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Trial balance. ?asOf= is the end of the period, the same as ?to= (send one, or both with the same date: different dates are refused). Accepts ?costCentreId=18f15bff-535b-5d77-b93c-7920ddb6e614 or the literal ?costCentreId=unallocated to restrict it to one branch, department or project; anything else is refused rather than widened to the whole company. ?compare=previous-year or previous-period adds the same trial balance over the prior range as comparative, as the statements do.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","periodLabel":"2026-09","rows":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","openingBalance":10005.0,"debit":1.0,"credit":1.0,"closingBalance":10005.0,"closingDebit":1.0,"closingCredit":1.0,"subtype":"text","isContra":false}],"totalDebit":10005.0,"totalCredit":10005.0,"totalClosingDebit":10005.0,"totalClosingCredit":10005.0,"balanced":true,"empty":true,"comparative":null},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/general-ledger?accountId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&from=2026-03-01&to=2027-02-28&costCentreId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"General ledger detail for an account. Takes the same ?costCentreId= filter as the trial balance, brought-forward balance included.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","periodLabel":"2026-09","accounts":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","openingBalance":10005.0,"lines":[{"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","date":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","description":"Consulting services — August 2026","contactName":"Karoo Fresh Holdings Ltd","costCentreCode":"CT-001","debit":1.0,"credit":1.0,"balance":10005.0}],"totalDebit":10005.0,"totalCredit":10005.0,"closingBalance":10005.0}],"empty":true},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/commissions?from=2026-10-01&to=2026-10-31","summary":"Each salesperson's commission for a period, worked out from the lines Sales & Margin reads. Nothing is stored but the rate.","auth":"jwt","responseExample":{"periodLabel":"1 October 2026 – 31 October 2026","rows":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Nkosi","ratePercent":5.0,"basis":"margin","earnedOn":"issued","revenue":18000.0,"margin":9000.0,"commissionable":9000.0,"commission":450.0,"employeeId":"7c2e9b14-0d3a-4f6e-8b21-5a9c1d7e3f40"}],"totalCommission":450.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/reports/commissions/rates","summary":"Set a salesperson's rate, on revenue or margin, earned when a document is issued or as it is paid.","auth":"jwt","body":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ratePercent":5.0,"basis":"margin","earnedOn":"issued"},"responseExample":{"ok":true},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/reports/commissions/to-payroll","summary":"Put each person's commission for the dates on their payslip for the period. Sending again replaces it; anyone not on the payroll is named.","auth":"jwt","body":{"from":"2026-10-01","to":"2026-10-31","periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"sent":1,"total":450.0,"skipped":[]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/sales-analysis?from=2026-03-01&to=2027-02-28&by=item&tag=Retail","summary":"Sales by item, customer or salesperson (`by=item|customer|rep`), with quantity, revenue, cost of sales and realised margin, read from invoice lines net of credit notes, with the cost each line consumed from stock. A line coded to an account the income statement puts outside revenue (Sundry Income, say) is other income, not a sale, and is left out. The totals are compared with the income statement for the same period and the response says whether they reconcile.","auth":"jwt","responseExample":{"periodLabel":"1 March 2026 – 28 February 2027","by":"item","rows":[{"key":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Hiking boots","quantity":12.0,"revenue":18000.0,"costOfSales":10800.0,"margin":7200.0,"marginPct":40.0}],"totalQuantity":12.0,"totalRevenue":18000.0,"totalCostOfSales":10800.0,"totalMargin":7200.0,"incomeStatementRevenue":18000.0,"ledgerCostOfGoodsSold":10800.0,"revenueDifference":0.0,"costOfSalesDifference":0.0,"reconciles":true},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/purchase-analysis?from=2026-03-01&to=2027-02-28&by=supplier","summary":"Purchases by item or supplier (`by=item|supplier`), from bill lines, VAT-exclusive and in the base currency.","auth":"jwt","responseExample":{"periodLabel":"1 March 2026 – 28 February 2027","by":"supplier","rows":[{"key":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","quantity":40.0,"amount":24000.0}],"totalAmount":24000.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/income-by-cost-centre?from=2026-03-01&to=2027-02-28&dimension=1","summary":"The income statement with one column per cost centre — the departmental or branch P&L, for one legal entity with several branches. Every column and the total come from one read of journal_lines through the one income-statement classifier, and the response says whether the columns reconcile to the company total rather than leaving the reader to add them up.","auth":"jwt","responseExample":{"periodLabel":"2026-09","from":"2026-09-01","to":"2026-09-30","columns":[{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","kind":"standard","isActive":true,"statement":{"periodLabel":"2026-09","revenue":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"costOfSales":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"operatingExpenses":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"otherIncome":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"tax":1305.0},"netProfit":8700.0}],"total":{"periodLabel":"2026-09","revenue":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"costOfSales":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"operatingExpenses":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"otherIncome":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"tax":1305.0},"totalNetProfit":8700.0,"reconciliationDifference":1.0,"reconciles":true,"unconfigured":true},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/drill-down/{accountId}?from=2026-03-01&to=2027-02-28","summary":"The transactions behind a figure, for click-through from a chart.","auth":"jwt","responseExample":{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","from":"2026-09-01","to":"2026-09-30","lines":[{"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","date":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","description":"Consulting services — August 2026","contactName":"Karoo Fresh Holdings Ltd","costCentreCode":"CT-001","debit":1.0,"credit":1.0,"balance":10005.0}],"totalDebit":10005.0,"totalCredit":10005.0,"net":8700.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/aged-debtors?asOf=2027-02-28","summary":"Aged debtors with the per-bucket breakdown the chart draws.","auth":"jwt","responseExample":{"asOfLabel":"Karoo Fresh Holdings Ltd","buckets":[{"label":"Karoo Fresh Holdings Ltd","amount":10005.0,"colorHex":"#0D47A1"}],"total":10005.0,"ledgerControlBalance":10005.0,"controlDifference":1.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/aged-creditors?asOf=2027-02-28","summary":"Aged creditors.","auth":"jwt","responseExample":{"asOfLabel":"Karoo Fresh Holdings Ltd","buckets":[{"label":"Karoo Fresh Holdings Ltd","amount":10005.0,"colorHex":"#0D47A1"}],"total":10005.0,"ledgerControlBalance":10005.0,"controlDifference":1.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/budget-vs-actual?period=2026-08&from=2026-03-01&to=2027-02-28","summary":"Budget against actual with variance.","auth":"jwt","responseExample":{"periodLabel":"2026-09","categories":[{"category":"Office supplies","budget":1.0,"actual":1.0}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/audit-trail/records/{type}/{id}?page=1&limit=50","summary":"One document's history, newest first: who created, changed, sent, voided or paid it, and what changed. type is invoice (quotes and credit notes included), bill or journal. Gated by the document's own permission (invoices:view, expenses:view, reports:view for a journal); a document in another business, or in a company the caller cannot reach, is a 404.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorEmail":"accounts@karoofresh.example","actorName":"Karoo Fresh Holdings Ltd","action":"created","resourceType":"standard","resourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","severity":"text","payload":"text","ipAddress":"12 Long Street, Cape Town, 8001","userAgent":"text","createdAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/audit-trail?from=2026-09-01&to=2026-09-30&actor=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&resourceType=invoice&page=1&limit=50","summary":"Who changed what in the books, and when: every audit row about invoices, bills, journals, periods, bank lines, stock, assets and contacts, newest first. Never sign-ins, roles, keys or payroll, and no IP address or browser. Needs reports:view; a person confined to some companies of a group is refused, because the trail is the whole organisation's. from and to are South African days, both inclusive. Add format=csv for every matching row as a sheet. The `actor` filter takes a user id or the email address a person signs in with (an email nobody in the business has shows no rows).","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","actorEmail":"accounts@karoofresh.example","actorName":"Karoo Fresh Holdings Ltd","action":"created","resourceType":"standard","resourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","severity":"text","payload":"text","ipAddress":"12 Long Street, Cape Town, 8001","userAgent":"text","createdAt":"2026-09-01T09:15:00Z"}],"total":42,"page":1,"limit":50},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/audit-trail/people","summary":"Who the books audit trail has rows for, by name and email, so a screen can offer a person filter that is a list and not a user id. A visiting accountant is listed like anyone else. The `userId` is what `actor` takes. Needs reports:view.","auth":"jwt","responseExample":{"people":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Anele Dlamini","email":"anele@practice.example"}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/vat-audit?from=2026-07-01&to=2026-08-31&format=json","summary":"The VAT201's support pack: every document behind each field — the invoices and credit notes in fields 1, 2 and 4, the bills and expense claims in field 15 — with its value and VAT, and each field's total, which is the return's. Add format=csv for the file a SARS verification asks for.","auth":"jwt","responseExample":{"periodLabel":"1 July 2026 – 31 August 2026","rows":[{"field":"1 / 4","category":"standard","source":"sale","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-2026-0042 (invoice)","date":"2026-07-14","counterparty":"Karoo Fresh Holdings Ltd","value":10000.0,"vat":1500.0}],"fields":[{"code":"1","label":"Standard-rated supplies, including VAT","amount":11500.0,"documents":1},{"code":"4","label":"Output tax","amount":1500.0,"documents":1}],"totalOutputVat":1500.0,"totalInputVat":0.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/vat-analysis?from=2026-07-01&to=2026-08-31","summary":"VAT by rate and by account, which is what a VAT201 is reconciled against.","auth":"jwt","responseExample":{"periodLabel":"2026-09","periods":[{"month":"2026-09","standardRatedSales":1.0,"zeroRatedSales":1.0,"outputVat":1305.0,"inputVat":1305.0,"netVat":1305.0}],"totalOutputVat":1305.0,"totalInputVat":1305.0,"totalNetVat":1305.0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/bbbee","summary":"The B-BBEE scorecard — six elements and the resulting level.","auth":"jwt","responseExample":{"level":1,"totalScored":1,"totalMax":1,"recognitionPct":1,"elements":[{"element":"text","maxPoints":1,"scored":1,"pct":1}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/reports/bbbee","summary":"Record the inputs the scorecard cannot derive from the books.","auth":"jwt","body":{"elements":[{"element":"ownership","score":18},{"element":"skills_development","score":11}]},"responseExample":{"level":1,"totalScored":1,"totalMax":1,"recognitionPct":1,"elements":[{"element":"text","maxPoints":1,"scored":1,"pct":1}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/scheduled","summary":"Scheduled report subscriptions.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reportType":"income","frequency":"monthly","nextRun":"text","recipients":"text","format":"CSV","active":true,"lastRun":"text","lastStatus":"text"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/reports/scheduled","summary":"Schedule a report.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reportType":"income","frequency":"monthly","nextRun":"text","recipients":"text","format":"CSV","active":true,"lastRun":"text","lastStatus":"text"},"body":{"name":"Monthly management pack","reportType":"income","frequency":"monthly","nextRun":"2026-09-01","recipients":"finance@karoofresh.example","format":"pdf","active":true,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customReportId":null,"packId":null},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/reports/scheduled/{id}","summary":"Change or pause a schedule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reportType":"income","frequency":"monthly","nextRun":"text","recipients":"text","format":"CSV","active":true,"lastRun":"text","lastStatus":"text"},"body":{"name":"Karoo Fresh Holdings Ltd","reportType":"income","frequency":"monthly","nextRun":"2026-10-01","recipients":"finance@karoofresh.example","format":"CSV","active":false},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/reports/scheduled/{id}","summary":"Remove a schedule.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/break-even?from=2026-03-01&to=2027-02-28","summary":"Break-even analysis for the period, read off the income statement: revenue, costs split into fixed and variable, contribution margin, break-even revenue and margin of safety. Every counted account is listed with whether its behaviour was stated or is its section default (cost of sales variable, operating expenses fixed). Other income and tax are left out; the split ties back to the statement's cost of sales and operating expenses.","auth":"jwt","responseExample":{"periodLabel":"2026-09","from":"2026-09-01","to":"2026-09-30","revenue":1.0,"variableCosts":10005.0,"fixedCosts":10005.0,"contributionMargin":1.0,"contributionMarginRatio":1.0,"breakEvenRevenue":1.0,"marginOfSafety":1.0,"marginOfSafetyRatio":1.0,"operatingProfit":1.0,"costOfSales":10005.0,"operatingExpenses":1.0,"tiesToIncomeStatement":true,"notComputable":"text","accounts":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","section":"text","amount":10005.0,"behaviour":"text","stated":true}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/reports/break-even/cost-behaviour?from=2026-03-01&to=2027-02-28","summary":"State whether one cost-of-sales or expense account is fixed or variable for break-even, or send null to return it to its section default. Answers the recomputed analysis for the period in the query. An unknown behaviour, or an account that is not a cost, is refused.","auth":"jwt","body":{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","behaviour":"variable"},"responseExample":{"periodLabel":"2026-09","from":"2026-09-01","to":"2026-09-30","revenue":1.0,"variableCosts":10005.0,"fixedCosts":10005.0,"contributionMargin":1.0,"contributionMarginRatio":1.0,"breakEvenRevenue":1.0,"marginOfSafety":1.0,"marginOfSafetyRatio":1.0,"operatingProfit":1.0,"costOfSales":10005.0,"operatingExpenses":1.0,"tiesToIncomeStatement":true,"notComputable":"text","accounts":[{"accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","section":"text","amount":10005.0,"behaviour":"text","stated":true}]},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/custom","summary":"The tenant's saved custom reports — each a definition (period grouping, dimensions, measures, filters), never a stored result.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","definition":{"name":"Karoo Fresh Holdings Ltd","periodGrouping":"2026-09","dimensions":["text"],"measures":["text"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["text"]}},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/reports/custom","summary":"Save a custom report definition. An unknown grouping, figure or filter is refused by name rather than dropped, and a name already in use (ignoring case) answers 409.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","definition":{"name":"Karoo Fresh Holdings Ltd","periodGrouping":"2026-09","dimensions":["text"],"measures":["text"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["text"]}},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Margin by customer","periodGrouping":"quarter","dimensions":["customer","costCentre"],"measures":["revenue","costOfSales","grossProfit","grossMargin","netProfit"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["revenue"]}},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"PUT","path":"/api/reports/custom/{id}","summary":"Change a saved custom report's definition or name.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","definition":{"name":"Karoo Fresh Holdings Ltd","periodGrouping":"2026-09","dimensions":["text"],"measures":["text"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["text"]}},"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Margin by customer","periodGrouping":"quarter","dimensions":["customer","costCentre"],"measures":["revenue","costOfSales","grossProfit","grossMargin","netProfit"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["revenue"]}},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"DELETE","path":"/api/reports/custom/{id}","summary":"Remove a saved custom report.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/reports/custom/run?from=2026-03-01&to=2027-02-28","summary":"Run a custom report definition without saving it. Every row is the income statement for its slice of the ledger, the totals are the income statement for the whole slice, and reconciles says whether the rows add up to them.","auth":"jwt","responseExample":{"name":"Karoo Fresh Holdings Ltd","periodLabel":"2026-09","from":"2026-09-01","to":"2026-09-30","columns":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard"}],"rows":[{"labels":["Karoo Fresh Holdings Ltd"],"values":[10005.0]}],"totals":[10005.0],"reconciles":true,"filtered":true,"companies":["text"]},"body":{"name":"Margin by customer","periodGrouping":"quarter","dimensions":["customer","costCentre"],"measures":["revenue","costOfSales","grossProfit","grossMargin","netProfit"],"filters":{"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sections":["revenue"]}},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/custom/{id}/run?from=2026-03-01&to=2027-02-28","summary":"Re-run a saved custom report against the ledger as it stands.","auth":"jwt","responseExample":{"name":"Karoo Fresh Holdings Ltd","periodLabel":"2026-09","from":"2026-09-01","to":"2026-09-30","columns":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard"}],"rows":[{"labels":["Karoo Fresh Holdings Ltd"],"values":[10005.0]}],"totals":[10005.0],"reconciles":true,"filtered":true,"companies":["text"]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/tax-pack/contents?year=2026","summary":"What the annual tax pack for the financial year ending in `year` will contain, and — for every file left out — why: a return your plan does not include, one your role may not read, a period that has not ended, or a company that is not a VAT vendor or employer. Ledgr prepares these files and never submits them to SARS.","auth":"jwt","responseExample":{"entityName":"Karoo Fresh Holdings Ltd","yearEnd":1,"yearLabel":"Karoo Fresh Holdings Ltd","from":"2026-09-01","to":"2026-09-30","items":[{"fileName":"SignedPO-4417.pdf","title":"Karoo Fresh Holdings Ltd","included":true,"omittedBecause":"text"}],"notice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/tax-pack?year=2026","summary":"The annual tax pack as one zip: the trial balance, income statement and balance sheet, the fixed-asset register, the year's VAT201s, EMP201s and EMP501 where they apply, and the ITR14 working with its supporting trial balance, plus a README listing everything left out and why. A return with a blocking issue is left out and named, never emitted. Prepare-and-download only.","auth":"jwt","responseKind":"binary","module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/afs?format=json","summary":"The annual financial statement set — cover page, responsibility statement, four statements with comparatives and disclosure-driven notes.","auth":"jwt","responseExample":{"entity":{"name":"Karoo Fresh Holdings Ltd","tradingAs":"text","registrationNumber":"2021/123456/07","incomeTaxNumber":"INV-0001","vatNumber":"4123456789","companyType":"standard","address":"12 Long Street, Cape Town, 8001","natureOfBusiness":"Karoo Fresh Holdings Ltd","countryOfIncorporation":"text","presentationCurrency":"ZAR"},"yearStart":"2026-09-01","yearEnd":"2026-09-30","priorYearStart":"2026-09-01","priorYearEnd":"2026-09-30","currentColumnLabel":"Overtime","priorColumnLabel":"Overtime","presentationCurrency":"ZAR","rounding":"text","roundingNote":"Budget deferred to the next financial year.","hasComparatives":true,"consolidated":true,"cover":{"entityName":"Karoo Fresh Holdings Ltd","entityDescriptor":"text","registrationLine":"text","title":"Karoo Fresh Holdings Ltd","periodLine":"2026-09","preparationLine":"text","assuranceLine":"text","currencyLine":"text","contentsEntries":["text"]},"narrative":[{"key":"text","title":"Karoo Fresh Holdings Ltd","paragraphs":["text"],"requiresCompletion":false,"signatureLabels":["Karoo Fresh Holdings Ltd"]}],"financialPosition":{"key":"sofp","title":"Karoo Fresh Holdings Ltd","subtitle":"text","lines":[{"label":"Karoo Fresh Holdings Ltd","currentUnits":1,"priorUnits":1,"noteRef":1,"kind":"DETAIL","indent":1,"accountCodes":["CT-001"]}]},"profitOrLoss":{"key":"sofp","title":"Karoo Fresh Holdings Ltd","subtitle":"text","lines":[{"label":"Karoo Fresh Holdings Ltd","currentUnits":1,"priorUnits":1,"noteRef":1,"kind":"DETAIL","indent":1,"accountCodes":["CT-001"]}]},"changesInEquity":{"title":"Karoo Fresh Holdings Ltd","subtitle":"text","columns":[{"key":"text","label":"Karoo Fresh Holdings Ltd"}],"rows":[{"label":"Karoo Fresh Holdings Ltd","amounts":[1],"kind":"DETAIL"}]},"cashFlows":{"key":"sofp","title":"Karoo Fresh Holdings Ltd","subtitle":"text","lines":[{"label":"Karoo Fresh Holdings Ltd","currentUnits":1,"priorUnits":1,"noteRef":1,"kind":"DETAIL","indent":1,"accountCodes":["CT-001"]}]},"notes":[{"key":"text","number":1,"title":"Karoo Fresh Holdings Ltd","paragraphs":["text"],"tables":[{"labelHeading":"text","columns":["text"],"rows":[{"label":"Karoo Fresh Holdings Ltd","values":[],"texts":[],"kind":"DETAIL","indent":1}],"numeric":true}],"standardReference":"INV-0001"}],"leadSchedules":[{"statementKey":"text","lineLabel":"Karoo Fresh Holdings Ltd","currentUnits":1,"priorUnits":1,"accounts":[{"code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","currentUnits":1,"priorUnits":1}],"ties":true}],"compliance":{"entityType":"invoice","entityTypeLabel":"Karoo Fresh Holdings Ltd","governingStatute":"text","publicInterestScore":1,"pisComponents":[{"label":"Karoo Fresh Holdings Ltd","points":1,"basis":"invoice","supplied":false}],"assuranceRequirement":"audit","assuranceLabel":"Karoo Fresh Holdings Ltd","assuranceReason":"Budget deferred to the next financial year.","assuranceOverridden":true,"financialReportingStandard":"text","governingBodyTerm":"directors","governingBodyTermSingular":"text","responsibilityStatementTitle":"Karoo Fresh Holdings Ltd","governingBodyReportTitle":"Karoo Fresh Holdings Ltd","equityCaptionShareCapital":"text","equityCaptionRetained":"text","entityDisclosureNotes":["Budget deferred to the next financial year."]},"issues":[]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/afs/years","summary":"Which years an AFS set can be produced for.","auth":"jwt","responseExample":{"fiscalYearEndMonth":9,"defaultYearEnd":"2026-09-30","years":[{"yearEnd":"2026-09-30","yearStart":"2026-09-01","label":"Karoo Fresh Holdings Ltd","hasComparatives":true}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/reports/afs/settings?yearEnd=2027-02-28&year=2027","summary":"AFS presentation settings and the Companies Act public interest score inputs.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","financialYearEnd":"2026-09-30","consolidated":false,"status":"sent","rounding":"text","preparedBy":"text","preparedByCapacity":"text","approvedOn":"2026-09-01","governingBodyMembers":["text"],"practitionerName":"Karoo Fresh Holdings Ltd","practitionerFirm":"text","assuranceEngagement":"text","natureOfBusiness":"Karoo Fresh Holdings Ltd","goingConcernNote":"Budget deferred to the next financial year.","subsequentEventsNote":"Budget deferred to the next financial year.","ownersLoanTerms":"text","provisionsNote":"Warranty claims are settled within 12 months of sale; long-service awards after five years of service.","contingenciesNote":"Guarantee of R500 000 given to the bank for a related company; no outflow is expected.","noContingentLiabilities":false,"averageEmployees":1,"beneficialInterestHolders":1,"internallyCompiled":true,"ownerManaged":false,"publicCompany":false,"fiduciaryAssetsOverThreshold":false,"priorPeriodErrors":[{"journalNumber":"JNL-0042","nature":"The audit fee for the prior year was not accrued.","occurredIn":"prior_year","profitAccountCode":"6010"}],"locked":false,"approvedAt":"2026-09-01T08:00:00Z","approvedBy":"Thandi Mokoena","figuresHash":"3f1a7c925b640d4e9a112c7e8b4f6a033f1a7c925b640d4e9a112c7e8b4f6a03","history":[{"approvedOn":"2026-09-01","approvedAt":"2026-09-01T08:00:00Z","approvedBy":"Thandi Mokoena","figuresHash":"3f1a7c925b640d4e9a112c7e8b4f6a033f1a7c925b640d4e9a112c7e8b4f6a03","reopenedAt":"2026-09-14T08:00:00Z","reopenedBy":"Thandi Mokoena","reopenReason":"A June accrual was left out"}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"PUT","path":"/api/reports/afs/settings?yearEnd=2027-02-28&year=2027","summary":"Change the AFS settings. Status final (reports:approve) approves the set: it locks the year, stores the approved figures, and takes no further edit. Status draft with a reopenReason reopens the year and records who and why.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","financialYearEnd":"2026-09-30","consolidated":false,"status":"sent","rounding":"text","preparedBy":"text","preparedByCapacity":"text","approvedOn":"2026-09-01","governingBodyMembers":["text"],"practitionerName":"Karoo Fresh Holdings Ltd","practitionerFirm":"text","assuranceEngagement":"text","natureOfBusiness":"Karoo Fresh Holdings Ltd","goingConcernNote":"Budget deferred to the next financial year.","subsequentEventsNote":"Budget deferred to the next financial year.","ownersLoanTerms":"Unsecured; interest at the SARS official rate; repayable on 90 days' notice.","provisionsNote":"Warranty claims are settled within 12 months of sale; long-service awards after five years of service.","contingenciesNote":"Guarantee of R500 000 given to the bank for a related company; no outflow is expected.","noContingentLiabilities":false,"averageEmployees":1,"beneficialInterestHolders":1,"internallyCompiled":true,"ownerManaged":false,"publicCompany":false,"fiduciaryAssetsOverThreshold":false,"priorPeriodErrors":[{"journalNumber":"JNL-0042","nature":"The audit fee for the prior year was not accrued.","occurredIn":"prior_year","profitAccountCode":"6010"}],"locked":false,"approvedAt":"2026-09-01T08:00:00Z","approvedBy":"Thandi Mokoena","figuresHash":"3f1a7c925b640d4e9a112c7e8b4f6a033f1a7c925b640d4e9a112c7e8b4f6a03","history":[{"approvedOn":"2026-09-01","approvedAt":"2026-09-01T08:00:00Z","approvedBy":"Thandi Mokoena","figuresHash":"3f1a7c925b640d4e9a112c7e8b4f6a033f1a7c925b640d4e9a112c7e8b4f6a03","reopenedAt":"2026-09-14T08:00:00Z","reopenedBy":"Thandi Mokoena","reopenReason":"A June accrual was left out"}]},"body":{"status":"sent","rounding":"rand","preparedBy":"Mokoena & Co","preparedByCapacity":"Accounting officer","approvedOn":"2026-09-01","governingBodyMembers":["Thandi Mokoena"],"practitionerName":"Karoo Fresh Holdings Ltd","practitionerFirm":"Mokoena & Partners Inc.","assuranceEngagement":"Independent review","natureOfBusiness":"Karoo Fresh Holdings Ltd","goingConcernNote":"Budget deferred to the next financial year.","subsequentEventsNote":"Budget deferred to the next financial year.","ownersLoanTerms":"Unsecured; interest at the SARS official rate; repayable on 90 days' notice.","provisionsNote":"Warranty claims are settled within 12 months of sale; long-service awards after five years of service.","contingenciesNote":"Guarantee of R500 000 given to the bank for a related company; no outflow is expected.","noContingentLiabilities":false,"averageEmployees":1,"beneficialInterestHolders":1,"internallyCompiled":true,"ownerManaged":true,"publicCompany":false,"fiduciaryAssetsOverThreshold":false,"priorPeriodErrors":[{"journalNumber":"JNL-0042","nature":"The audit fee for the prior year was not accrued.","occurredIn":"prior_year","profitAccountCode":"6010"}],"reopenReason":"A June accrual was left out"},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/reports/afs/lead-schedules","summary":"The lead schedules behind each statement line. An account the preparer moved to this line (PUT /api/accounts/{id} statementClass) carries overridden: true.","auth":"jwt","responseExample":[{"statementKey":"text","lineLabel":"Karoo Fresh Holdings Ltd","currentUnits":1,"priorUnits":1,"accounts":[{"code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","currentUnits":1,"priorUnits":1}],"ties":true}],"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/report-tables","summary":"The flat, refreshable tables Excel can bind to. Accepts an API KEY directly as well as a JWT, because Power Query cannot run a token exchange and a monthly refresh cannot hold an hourly token.","auth":"api-key","responseKind":"json"},{"method":"GET","path":"/api/report-tables/{report}?format=csv&from=2026-03-01&to=2027-02-28","summary":"One table as JSON or CSV. Read-only, scope- and licence-checked explicitly.","auth":"api-key","responseKind":"csv"}]},{"name":"SARS returns","blurb":"Prepare and download. Ledgr computes each return and produces a file you capture on eFiling or import into e@syFile — it does NOT transmit. format=json always answers; a file format answers 422 with reasons when the return does not validate, so a wrong file is never emitted.","endpoints":[{"method":"GET","path":"/api/sars/overview","summary":"Per-tax-type filing state — last filed and next due.","auth":"jwt","responseExample":{"isvConfigured":false,"entityName":"Karoo Fresh Holdings Ltd","vatNumber":"4123456789","vatRegistered":false,"vatCategory":"Office supplies","vatCategoryLabel":"Karoo Fresh Holdings Ltd","vatCategoryAssumed":false,"vatCategoryWarning":"text","employer":false,"fiscalYearEndMonth":2,"taxTypes":[{"code":"CT-001","title":"Karoo Fresh Holdings Ltd","frequency":"monthly","lastFiledPeriod":"2026-09","lastFiledAt":"2026-09-01T09:15:00Z","lastStatus":"sent","nextDueDate":"2026-09-01","nextDuePeriod":"2026-09"}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"GET","path":"/api/sars/group-overview","summary":"Every company the caller may open — live, in this tenant, and within their company assignments — each with its legal form and the same returns, next due dates, latest filings and overdue returns as its own GET /api/sars/overview. Tenant-wide: send no X-Company-Id. The API sandbox is left out. Needs sars:view.","auth":"jwt","responseExample":{"companies":[{"companyId":"7f6c1a2e-0000-4000-8000-000000000010","name":"Dlamini & Venter","legalForm":"PARTNERSHIP","legalFormLabel":"Partnership","overview":{"isvConfigured":false,"entityName":"Dlamini & Venter","vatRegistered":false,"vatCategory":"NONE","fiscalYearEndMonth":2,"legalForm":"PARTNERSHIP","taxTypes":[{"code":"IT14","title":"ITR12 business income schedule","frequency":"Annual","nextDueDate":"2027-01-18","nextDuePeriod":"Year ending Feb 2026"}]}}]},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents","summary":"Which returns can be produced, and for which periods.","auth":"jwt","responseExample":{"entityName":"Karoo Fresh Holdings Ltd","documents":[{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","frequency":"monthly","submissionChannel":"email","formats":["CSV"],"path":"text","parameters":["text"],"available":true,"unavailableReason":"Budget deferred to the next financial year."}],"easyFileUnverifiedCodes":["CT-001"],"manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/vat201?corrected=true&from=2026-07-01&to=2026-08-31&format=json","summary":"The VAT201. Output-tax supplies come from one owner — OutputTaxSupplies in shared — because omitting credit notes, debit notes and deposits once declared a refund of R6 353.49 where R6 336.81 was payable.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":["CSV"],"manualSubmissionOnly":true},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"GET","path":"/api/sars/documents/emp201?year=2026&month=8&format=json","summary":"The EMP201 — PAYE, UIF, SDL and the ETI set off against them.","auth":"jwt","responseExample":{"taxType":"EMP201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":["CSV"],"manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/emp501?taxYear=2027&format=json&period=2","summary":"The EMP501 bi-annual reconciliation.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":["CSV"],"manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/irp5?taxYear=2027&format=easyfile&layout=BRS&period=2","summary":"IRP5/IT3(a) certificates, reviewed per employee before generation — e@syFile rejects a whole import on one bad record.","auth":"jwt","responseKind":"text","module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/itr14?year=2027&format=json&partner=7f6c1a2e-0000-4000-8000-000000000011","summary":"The annual income tax return the legal form files (ITR14, ITR12T, ITR12EI, or the owner's or partners' ITR12 business income schedule). For a partnership it carries the partnership's schedule and one per partner; `partner=<id>` answers that one partner's share alone, for their own ITR12 — each line is the partnership's × their share, the largest share carrying the rounding so the partners add up to the cent. The account-type alias is folded once, in Itr14TrialBalanceLine's constructor, because an imported chart labelling its accounts `revenue` rather than `income` once reported nil turnover.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":["CSV"],"manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/itr14/trial-balance?year=2027&format=csv","summary":"The trial-balance CSV that ships as the ITR14's supporting schedule.","auth":"jwt","responseKind":"csv","module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/irp6?year=2027&period=1&format=json&basis=annualised&estimate=150000","summary":"The IRP6 provisional tax return.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":["CSV"],"manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/dividends","summary":"Dividend declarations behind the DTR01/DTR02.","auth":"jwt","responseExample":{"declarations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","declarationDate":"2026-09-01","paymentDate":"2026-09-01","dividendDeclared":1.0,"exemptAmount":10005.0,"taxableAmount":1305.0,"dividendsTax":1305.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","beneficialOwners":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","taxReferenceNumber":"INV-0001","identityOrRegistrationNumber":"2021/123456/07","countryOfResidence":"text","dividendAmount":10005.0,"exemptAmount":10005.0,"exemptionGround":"text","exemptionReason":"Budget deferred to the next financial year.","declarationReceivedDate":"2026-09-01","treatyRatePercent":15.0,"taxableAmount":1305.0,"ratePercent":15.0,"taxWithheld":1305.0}],"dueDate":"2026-09-01","statutoryRatePercent":15.0,"blockingIssues":["The control account and the age analysis differ by R0.00."],"createdAt":"2026-09-01T09:15:00Z"}]},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/documents/dividends","summary":"Record a dividend declaration. It posts to the ledger: DR 3600 Dividends Declared / CR 2190 Shareholders for Dividends, then the dividends tax withheld moves to 2171 on the payment date. Refused without the date of the board's (a close corporation's members') resolution acknowledging the solvency and liquidity test (Companies Act s46; CC Act s51), or when payment is more than 120 business days after it; the books' side of the test is returned in solvencyTest.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","declarationDate":"2026-09-01","paymentDate":"2026-09-01","dividendDeclared":1.0,"exemptAmount":10005.0,"taxableAmount":1305.0,"dividendsTax":1305.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","beneficialOwners":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","taxReferenceNumber":"INV-0001","identityOrRegistrationNumber":"2021/123456/07","countryOfResidence":"text","dividendAmount":10005.0,"exemptAmount":10005.0,"exemptionGround":"text","exemptionReason":"Budget deferred to the next financial year.","declarationReceivedDate":"2026-09-01","treatyRatePercent":15.0,"taxableAmount":1305.0,"ratePercent":15.0,"taxWithheld":1305.0}],"dueDate":"2026-09-01","statutoryRatePercent":15.0,"blockingIssues":["The control account and the age analysis differ by R0.00."],"createdAt":"2026-09-01T09:15:00Z","solvencyTest":{"boardResolutionDate":"2026-08-15","assets":1250000.0,"liabilitiesAfter":640000.0,"currentAssets":480000.0,"currentLiabilitiesAfter":390000.0,"solventOnBooks":true,"liquidOnBooks":true,"warnings":[]}},"body":{"declarationDate":"2026-08-15","paymentDate":"2026-08-31","dividendDeclared":250000.0,"reference":"DIV-2026-01","notes":"Budget deferred to the next financial year.","beneficialOwners":[{"name":"Karoo Fresh Holdings Ltd","kind":"natural_person","taxReferenceNumber":"INV-0001","identityOrRegistrationNumber":"2021/123456/07","countryOfResidence":"ZA","dividendAmount":10005.0,"exemptAmount":10005.0,"exemptionGround":"resident_company","exemptionReason":"Budget deferred to the next financial year.","declarationReceivedDate":"2026-09-01","treatyRatePercent":15.0}],"boardResolutionDate":"2026-08-15","solvencyAndLiquidityAcknowledged":true,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"DELETE","path":"/api/sars/documents/dividends/{id}","summary":"Remove a declaration, reversing its ledger journals.","auth":"jwt","responseKind":"none","module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/donation-receipts?page=1&limit=50&before=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Section 18A donation receipts this company issued, newest first, one page at a time (?limit=50, at most 200; the next page is ?before=<id of the last receipt shown>, so a receipt issued meanwhile never shifts it; ?page= still answers), and whether it may issue one.","auth":"jwt","responseExample":{"applies":true,"refusal":null,"receipts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"18A-00001","donationDate":"2026-09-01","amount":5000.0,"nature":null,"contactId":"9b2e4d61-7a3c-4f85-b0d2-6e1f8a9c3b47","donorName":"Thandi Mokoena","donorTradingName":null,"donorAddress":"12 Long Street, Cape Town, 8001","donorPhone":"0214441234","donorEmail":"thandi@example.example","donorNature":"INDIVIDUAL","donorIdType":"SA_ID","donorIdNumber":"8001015009087","donorIdCountry":"ZA","donorTaxNumber":"0123456789","issuedAt":"2026-09-01T09:30:00+02:00","lastSentAt":null,"lastSendDelivered":null}],"total":1,"page":1,"limit":50,"totalPages":1},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/donation-receipts","summary":"Issue a numbered section 18A receipt for a donation; refused unless the company is an approved PBO with section 18A approval. A clientId (a UUID the client mints once per receipt) makes a re-send answer the receipt already issued (200, the same number) instead of issuing a second.","auth":"jwt","body":{"contactId":"9b2e4d61-7a3c-4f85-b0d2-6e1f8a9c3b47","donationDate":"2026-09-01","amount":5000.0,"nature":null,"donorNature":"INDIVIDUAL","donorIdType":"SA_ID","donorIdNumber":"8001015009087","donorIdCountry":"ZA","donorTaxNumber":"0123456789","clientId":"c4d8e2f1-6a3b-4e97-8d15-0b2f9a7c5e64"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"18A-00001","donationDate":"2026-09-01","amount":5000.0,"nature":null,"contactId":"9b2e4d61-7a3c-4f85-b0d2-6e1f8a9c3b47","donorName":"Thandi Mokoena","donorTradingName":null,"donorAddress":"12 Long Street, Cape Town, 8001","donorPhone":"0214441234","donorEmail":"thandi@example.example","donorNature":"INDIVIDUAL","donorIdType":"SA_ID","donorIdNumber":"8001015009087","donorIdCountry":"ZA","donorTaxNumber":"0123456789","issuedAt":"2026-09-01T09:30:00+02:00","lastSentAt":null,"lastSendDelivered":null},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/donation-receipts/{id}/pdf","summary":"The receipt as the donor is sent it.","auth":"jwt","responseKind":"pdf","module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/donation-receipts/{id}/send","summary":"Email the receipt to the donor; the attempt is recorded on their communication history.","auth":"jwt","responseExample":{"delivered":true,"error":null,"receipt":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptNumber":"18A-00001","donationDate":"2026-09-01","amount":5000.0,"nature":null,"contactId":"9b2e4d61-7a3c-4f85-b0d2-6e1f8a9c3b47","donorName":"Thandi Mokoena","donorTradingName":null,"donorAddress":"12 Long Street, Cape Town, 8001","donorPhone":"0214441234","donorEmail":"thandi@example.example","donorNature":"INDIVIDUAL","donorIdType":"SA_ID","donorIdNumber":"8001015009087","donorIdCountry":"ZA","donorTaxNumber":"0123456789","issuedAt":"2026-09-01T09:30:00+02:00","lastSentAt":"2026-09-01T09:35:00+02:00","lastSendDelivered":true}},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/documents/dtr01/{declarationId}?format=json","summary":"The DTR01 for one declaration.","auth":"jwt","responseKind":"json","module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/tt03?year=2027&format=json","summary":"The TT03 turnover-tax return working document for the year of assessment ending in February of `year` (default: the year just ended): the amounts received in the year, the tax on the table, the interim payments made (money paid to SARS, not interims noted as filed) and the balance. Prepare-and-download only. A year the company is not registered for blocks (TT_NOT_REGISTERED). Needs sars:view; files need sars:export.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":"html","manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/it3d?year=2027&period=first&format=json","summary":"The IT3(d) working document of the section 18A receipts an approved public benefit organisation issued, for `period` first (1 March to 31 August, due 31 October) or year (the full year of assessment ending in February of `year`, due 31 May): the receipts issued and their rand value, the donations received on Donations Received (4160) in the same months, the difference, and each side's unmatched entries listed (receipts with no donation; donations with no receipt). Refused with 409 unless the company is an approved PBO with a section 18A approval. Prepare-and-download only. Needs sars:view; files need sars:export.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":"html","manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/documents/it3t?year=2027&format=json","summary":"The IT3(t) working document of what a trust vested in each beneficiary in the year of assessment ending in February of `year` (default: the last completed year): the year's debits less credits to 3700 Distributions Vested in Beneficiaries, by the beneficiary named as the line's contact, each divided between local interest (source code 4201) and other income (4214) in proportion to the trust's income for the year (the conduit principle, s25B), the total vested (which the ITR12T deducts under section 25B), and a warning for any vesting that names no beneficiary. Refused with 409 unless the company is a trust. Prepare-and-download only: Ledgr does not write SARS's IT3(t) file. Needs sars:view; files need sars:export.","auth":"jwt","responseExample":{"taxType":"VAT201","title":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","entityName":"Karoo Fresh Holdings Ltd","taxReferenceNumber":"INV-0001","sections":[{"title":"Karoo Fresh Holdings Ltd","note":"Budget deferred to the next financial year.","fields":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","kind":"invoice","amount":10005.0,"display":"text","unmapped":false,"confidence":"text","note":"Budget deferred to the next financial year."}]}],"issues":[],"blockingIssues":["The control account and the age analysis differ by R0.00."],"warnings":[],"unmappedFields":["text"],"unverifiedFieldCodes":["CT-001"],"derivedPaymentReference":"INV-0001","netAmount":8700.0,"isRefund":false,"availableFormats":"html","manualSubmissionOnly":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/documents/it3d/file","summary":"The IT3(d) as a file in SARS's External BRS IT3 Data Submission layout (v4.0.0D-10, section 6.5): pipe-delimited Latin-1 records, one donor record per donor and one donation record per receipt, with a trailer that counts and hashes them. `sourceIdentifier` is the 144-character token SARS issues the submitter; it is written into the file and never stored. `testData` marks the file for SARS's test environment. A return with a blocking issue answers 422; a company that is not an approved PBO with a section 18A approval answers 409. Ledgr does not transmit it. Needs sars:export.","auth":"jwt","body":{"year":2027,"period":"first","sourceIdentifier":"<the 144 characters SARS issued>","testData":true},"responseKind":"text","module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/vat201?from=2026-07-01&to=2026-08-31","summary":"The computed VAT201 boxes, as the screen renders them.","auth":"jwt","responseExample":{"periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09","standardRatedSales":1.0,"zeroRatedSales":1.0,"exemptSupplies":1.0,"outputVat":1305.0,"inputVat":1305.0,"unclaimableInputTax":1305.0,"apportionmentPercent":15.0,"netVat":1305.0,"entityName":"Karoo Fresh Holdings Ltd","vatNumber":"4123456789","vatRegistered":false,"vatCategory":"Office supplies","vatCategoryLabel":"Karoo Fresh Holdings Ltd","vatCategoryAssumed":false,"vatCategoryWarning":"text","isvConfigured":false},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"GET","path":"/api/sars/section-24c-claims?yearEnd=2026-02-28","summary":"The section 24C claims recorded for a year end and the cap the books put on them: one claim per identified contract, the allowance the lesser of the income received in advance and the expenditure still to be incurred, limited to the income received in advance the books hold. The ITR14 deducts it and deferred tax reads the same.","auth":"jwt","responseExample":{"yearEnd":"2026-02-28","claims":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","yearEnd":"2026-02-28","contractRef":"SLA-2025-14","contractDate":"2025-11-03","incomeReceivedInAdvance":18000.0,"futureExpenditure":10000.0,"allowance":10000.0}],"claimed":10000.0,"incomeReceivedInAdvance":18000.0,"allowed":10000.0},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/section-24c-claims","summary":"Record the section 24C allowance claimed on one identified contract at a year end. Refuses (400) a claim with no contract reference or date, amounts at or below nil, a contract concluded after the year end, or a date that is not the end of a year of assessment (the company's year end; February for a trust or a sole proprietor).","auth":"jwt","body":{"yearEnd":"2026-02-28","contractRef":"SLA-2025-14","contractDate":"2025-11-03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a05","incomeReceivedInAdvance":18000.0,"futureExpenditure":10000.0,"note":"Annual support contract"},"responseExample":{"yearEnd":"2026-02-28","claims":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","yearEnd":"2026-02-28","contractRef":"SLA-2025-14","contractDate":"2025-11-03","incomeReceivedInAdvance":18000.0,"futureExpenditure":10000.0,"allowance":10000.0}],"claimed":10000.0,"incomeReceivedInAdvance":18000.0,"allowed":10000.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"DELETE","path":"/api/sars/section-24c-claims/{id}","summary":"Take a section 24C claim back; the ITR14 and deferred tax stop reading it. Answers the year end's claims.","auth":"jwt","responseExample":{"yearEnd":"2026-02-28","claims":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","yearEnd":"2026-02-28","contractRef":"SLA-2025-14","contractDate":"2025-11-03","incomeReceivedInAdvance":18000.0,"futureExpenditure":10000.0,"allowance":10000.0}],"claimed":10000.0,"incomeReceivedInAdvance":18000.0,"allowed":10000.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/prepaid-expenses?asOf=2026-02-28","summary":"The prepaid expenses register at a date beside account 1330: each payment with whether section 23H defers it (supplied within six months after the year end, or R100 000 or less, is deducted when paid), what is unexpired, the expense account it is released to and what the month ends have released to it by the date, and the part of 1330 the register does not explain.","auth":"jwt","responseExample":{"asOf":"2026-02-28","expenses":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a04","description":"Software licence, 12 months","paidOn":"2025-12-01","amount":60000.0,"serviceStart":"2025-12-01","serviceEnd":"2026-11-30","exempt":true,"exemptReason":"R100 000 or less","unexpired":45205.48,"expenseAccountCode":"6230","released":14794.52}],"unexpired":45205.48,"deductedWhenPaid":45205.48,"accountBalance":45205.48,"unclassified":0.0},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/prepaid-expenses","summary":"Classify a payment held in 1330 as a prepaid expense: what it was, the day paid, the amount, the first and last day of the service and the expense account it is released to (optional: with one, each month end moves the month's share from 1330 to it, IFRS for SMEs 2.36). Refuses (400) a missing description or date, an amount at or below nil, a service that ended before the payment, and an expense account that is not an expense or cost-of-sales account in the company's chart.","auth":"jwt","body":{"description":"Software licence, 12 months","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a06","paidOn":"2025-12-01","amount":60000.0,"serviceStart":"2025-12-01","serviceEnd":"2026-11-30","expenseAccountCode":"6230"},"responseExample":{"asOf":"2026-02-28","expenses":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a04","description":"Software licence, 12 months","paidOn":"2025-12-01","amount":60000.0,"serviceStart":"2025-12-01","serviceEnd":"2026-11-30","exempt":true,"exemptReason":"R100 000 or less","unexpired":45205.48,"expenseAccountCode":"6230","released":14794.52}],"unexpired":45205.48,"deductedWhenPaid":45205.48,"accountBalance":45205.48,"unclassified":0.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"DELETE","path":"/api/sars/prepaid-expenses/{id}","summary":"Take a prepaid expense out of the register; the ITR14 and deferred tax stop reading it. Answers the register today.","auth":"jwt","responseExample":{"asOf":"2026-02-28","expenses":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a04","description":"Software licence, 12 months","paidOn":"2025-12-01","amount":60000.0,"serviceStart":"2025-12-01","serviceEnd":"2026-11-30","exempt":true,"exemptReason":"R100 000 or less","unexpired":45205.48,"expenseAccountCode":"6230","released":14794.52}],"unexpired":45205.48,"deductedWhenPaid":45205.48,"accountBalance":45205.48,"unclassified":0.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/vat201/pre-filing-check?from=2026-07-01&to=2026-08-31","summary":"What to look at before a VAT201 is noted as filed: the VAT control tie, bank lines in the period not booked, purchases whose input tax was withheld for want of the supplier's VAT number, documents captured after the return was prepared, and apportionment. Advice only; each warning names its remedy.","auth":"jwt","responseExample":{"periodStart":"2026-07-01","periodEnd":"2026-08-31","items":[{"code":"input_withheld","severity":"warn","title":"1 purchase left out R1 500.00 of input tax for want of the supplier's VAT number","detail":"A purchase over R5 000 is claimed only with the supplier's VAT number on a tax invoice (VAT Act s16(2) and s20); these were posted to cost instead, so the return does not claim them.","remedy":"Add the supplier's VAT number to the contact (the purchase is claimed from then on), or leave it as cost if the supplier is not a vendor.","amount":1500.0,"count":1}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"POST","path":"/api/sars/vat201/submit","summary":"Note the VAT201 for a period as filed. The reference recorded is LEDGR'S OWN — nothing is transmitted to SARS. Optionally keep what eFiling issued: sarsReference, filedOn, and the payment (paidOn with paidAmount); a date before the period ended or in the future is refused (400). Refuses (409) a window that is not one ended VAT period of the company's category, or that overlaps a return already filed.","auth":"jwt","body":{"periodStart":"2026-07-01","periodEnd":"2026-08-31","sarsReference":"EFL-2026-0007","filedOn":"2026-09-03","paidOn":"2026-09-03","paidAmount":18450.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"GET","path":"/api/sars/sbc?yearEnd=2027-02-28","summary":"The company's answers to the five s12E small business corporation tests for a year of assessment, and whether it qualifies (null until every test is answered, false on any no). A qualifying company's ITR14 and IRP6 are taxed on the SBC table for the year; an unanswered year is asked about on both returns. grossIncomeOnLedger is the year's income on the books, beside the R20 million test.","auth":"jwt","responseExample":{"yearEnd":"2027-02-28","shareholdersAllNaturalPersons":true,"grossIncomeWithinLimit":true,"noSharesInOtherCompanies":true,"investmentAndServiceIncomeWithinLimit":true,"notPersonalServiceProvider":true,"qualifies":true,"confirmedAt":"2026-10-13T08:00:00Z","grossIncomeOnLedger":500000.0},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"PUT","path":"/api/sars/sbc","summary":"Answer the five s12E tests for a year of assessment. A yes to the R20 million gross income test is refused when the books show more. Needs sars:edit.","auth":"jwt","body":{"yearEnd":"2027-02-28","shareholdersAllNaturalPersons":true,"grossIncomeWithinLimit":true,"noSharesInOtherCompanies":true,"investmentAndServiceIncomeWithinLimit":true,"notPersonalServiceProvider":true},"responseExample":{"yearEnd":"2027-02-28","shareholdersAllNaturalPersons":true,"grossIncomeWithinLimit":true,"noSharesInOtherCompanies":true,"investmentAndServiceIncomeWithinLimit":true,"notPersonalServiceProvider":true,"qualifies":true,"confirmedAt":"2026-10-13T08:00:00Z","grossIncomeOnLedger":500000.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/vat-basis","summary":"The company's VAT accounting basis today (invoice or payments), every dated change, and why it could not move onto the payments basis today (null when it qualifies). Needs sars:view.","auth":"jwt","responseExample":{"current":"payments","changes":[{"basis":"payments","effectiveFrom":"2026-09-01"}],"paymentsRefusal":null},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"PUT","path":"/api/sars/vat-basis","summary":"Record the VAT accounting basis from the first day of a tax period. The payments basis is refused for a company that is not a natural person or whose taxable supplies over the last twelve months exceed R2.5 million. Needs sars:edit.","auth":"jwt","body":{"basis":"payments","effectiveFrom":"2026-09-01"},"responseExample":{"current":"payments","changes":[{"basis":"payments","effectiveFrom":"2026-09-01"}],"paymentsRefusal":null},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"GET","path":"/api/sars/turnover-tax?year=2027","summary":"A micro business's turnover-tax estimate for a year of assessment: turnover so far and projected, the tax on the published table, both interim payments with their dates, and the TT03 window. A turnover above the limit is warned by name. Needs sars:view.","auth":"jwt","responseExample":{"taxYearEndYear":2027,"periodStart":"2026-03-01","periodEnd":"2027-02-28","registered":true,"turnoverToDate":600000.0,"completedMonths":6,"projectedTurnover":1200000.0,"taxOnTurnoverToDate":0.0,"estimatedTax":8500.0,"firstInterim":{"amount":4250.0,"dueDate":"2026-08-31"},"secondInterim":{"amount":4250.0,"dueDate":"2027-02-26"},"annualReturnOpens":"2027-07-01","annualReturnDue":"2028-01-31","turnoverLimit":2300000.0,"issues":[]},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"PUT","path":"/api/sars/turnover-tax/registration","summary":"Record that the company is (or is no longer) registered for turnover tax from 1 March of the year of assessment ending in February of `year`. Needs sars:edit.","auth":"jwt","body":{"year":2027,"registered":true},"responseExample":{"taxYearEndYear":2027,"periodStart":"2026-03-01","periodEnd":"2027-02-28","registered":true,"turnoverToDate":600000.0,"completedMonths":6,"projectedTurnover":1200000.0,"taxOnTurnoverToDate":0.0,"estimatedTax":8500.0,"firstInterim":{"amount":4250.0,"dueDate":"2026-08-31"},"secondInterim":{"amount":4250.0,"dueDate":"2027-02-26"},"annualReturnOpens":"2027-07-01","annualReturnDue":"2028-01-31","turnoverLimit":2300000.0,"issues":[]},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"POST","path":"/api/sars/turnover-tax/submit","summary":"Record a turnover-tax interim payment (`interim1`, `interim2`) or the TT03 (`tt03`) as filed on the filing register for the year of assessment ending in February of `year`; its row then leaves the deadline card. Prepare-and-download only: nothing is sent to SARS. Refused 409 for a year the company is not registered for. Needs sars:create.","auth":"jwt","body":{"year":2027,"kind":"interim2"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a04","submissionType":"TT_INTERIM","periodStart":"2026-09-01","periodEnd":"2027-02-28","totalPaye":0.0,"totalUif":0.0,"totalSdl":0.0,"totalEti":0.0,"totalPayable":0.0,"totalDue":4250.0,"status":"SUBMITTED","referenceNumber":"TT_INTERIM-202702-A1B2C3","submittedAt":"2027-02-20T09:15:00Z","createdAt":"2027-02-20T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/partners?year=2027","summary":"A partnership's partners and their shares for the ITR14 year ending in `year` (default: the last completed year) — the set in force at the year end, the one the partners' ITR12 schedules split by. Needs sars:view, not multicompany:view.","auth":"jwt","responseExample":{"companyId":"7f6c1a2e-0000-4000-8000-000000000010","partnership":true,"partners":[{"id":"7f6c1a2e-0000-4000-8000-000000000011","name":"Thandi Dlamini","taxNumber":"0123456789","sharePercent":60.0},{"id":"7f6c1a2e-0000-4000-8000-000000000012","name":"Pieter Venter","sharePercent":40.0}],"totalPercent":100.0},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars/vat-adjustments?from=2026-09-01&to=2026-09-30","summary":"The VAT adjustments recorded in a period, newest first: bad debts written off (VAT201 field 17) and recovered (field 12), and changes in use (fields 9/11 and 16), each with its reason and document. Defaults to the most recent closed VAT period. At most 500. Needs sars:view.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","adjustments":[{"id":"7f6c1a2e-0000-4000-8000-000000000001","kind":"bad_debt_written_off","kindLabel":"Bad debt written off","field":"17","date":"2026-09-30","invoiceId":"7f6c1a2e-0000-4000-8000-000000000002","invoiceNumber":"INV-0042","consideration":11500.0,"vatAmount":1500.0,"reason":"Customer liquidated; claim lodged with the liquidator","documentRef":"Liquidator's letter 2026/118","billId":null,"assetId":null}],"limit":500},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"POST","path":"/api/sars/vat-adjustments","summary":"Record a VAT adjustment with its reason. `bad_debt_written_off` writes `amount` (including VAT, at most the invoice's amount due) off and claims back the invoice's own VAT share (DR 6300, DR 1340, CR 1320); `bad_debt_recovered` reinstates up to what was written off (DR 1320, CR 6300, CR 2130) so the payment is then recorded on the invoice as usual; `change_in_use_output` / `change_in_use_input` take the open-market value including VAT (CR 2130 or DR 1340 against 6345). A bad debt written off by a company that is not a VAT vendor on the date claims no VAT (DR 6300 / CR 1320 only, `vatAmount` 0) — the invoice's own door, POST /api/invoices/{id}/bad-debts, is the same writer on every plan. A change in use may name its fixed asset (`assetId`): a `change_in_use_input` naming one claims the tax fraction of the lesser of `amount` and the asset's cost less earlier s18(4) claims on it, and a cost already claimed in full is refused. A change in use is refused for a company that is not a VAT vendor; a vendor's debt on the payments basis and a blank reason are refused. Needs sars:edit.","auth":"jwt","body":{"kind":"bad_debt_written_off","invoiceId":"7f6c1a2e-0000-4000-8000-000000000002","amount":11500.0,"date":"2026-09-30","reason":"Customer liquidated; claim lodged with the liquidator","documentRef":"Liquidator's letter 2026/118","billId":"7f6c1a2e-0000-4000-8000-000000000002","accountCode":"6340","assetId":"7f6c1a2e-0000-4000-8000-000000000003"},"responseExample":{"id":"7f6c1a2e-0000-4000-8000-000000000001","kind":"bad_debt_written_off","kindLabel":"Bad debt written off","field":"17","date":"2026-09-30","invoiceId":"7f6c1a2e-0000-4000-8000-000000000002","invoiceNumber":"INV-0042","consideration":11500.0,"vatAmount":1500.0,"reason":"Customer liquidated; claim lodged with the liquidator","documentRef":"Liquidator's letter 2026/118","billId":null,"assetId":null},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"GET","path":"/api/sars/vat-review","summary":"Past VAT in stored rows, each with its rand effect, tax period and route. Reads only.","auth":"jwt","responseExample":{"findings":[{"key":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"disposal_no_output_tax","periodStart":"2026-09-01","periodEnd":"2026-09-30","filed":true,"reference":"FA-0001","message":"Press was sold for R115 000.00 and no output tax was declared on it.","vatEffect":15000.0,"check":false,"route":"correction","press":"book_output_tax","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decision":null,"decisionReason":null}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"POST","path":"/api/sars/vat-review/act","summary":"The one press a finding offers: a posting or VAT adjustment on its own date, a release from a filed return's baseline, or a retype of an open period's export lines as a service, which posts nothing; a filed period's change reaches the correction schedule.","auth":"jwt","body":{"finding":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Checked with our accountant"},"responseExample":{"findings":[{"key":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"disposal_no_output_tax","periodStart":"2026-09-01","periodEnd":"2026-09-30","filed":true,"reference":"FA-0001","message":"Press was sold for R115 000.00 and no output tax was declared on it.","vatEffect":15000.0,"check":false,"route":"correction","press":"book_output_tax","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decision":null,"decisionReason":null}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"POST","path":"/api/sars/vat-review/dismiss","summary":"Record that a finding does not apply, with the reason. Nothing else moves.","auth":"jwt","body":{"finding":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Checked with our accountant"},"responseExample":{"findings":[{"key":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"disposal_no_output_tax","periodStart":"2026-09-01","periodEnd":"2026-09-30","filed":true,"reference":"FA-0001","message":"Press was sold for R115 000.00 and no output tax was declared on it.","vatEffect":15000.0,"check":false,"route":"correction","press":"book_output_tax","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decision":null,"decisionReason":null}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"POST","path":"/api/sars/vat-review/undo","summary":"Take a decision back, and the press with it.","auth":"jwt","body":{"finding":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"findings":[{"key":"disposal:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"disposal_no_output_tax","periodStart":"2026-09-01","periodEnd":"2026-09-30","filed":true,"reference":"FA-0001","message":"Press was sold for R115 000.00 and no output tax was declared on it.","vatEffect":15000.0,"check":false,"route":"correction","press":"book_output_tax","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","decision":null,"decisionReason":null}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"POST","path":"/api/bills/{billId}/debit-notes","summary":"Raise the supplier's debit note, a further charge that pays as a bill; field 18 when the bill was on a filed return.","auth":"jwt","body":{"creditNoteNumber":"DN-4471","issueDate":"2026-09-30","reason":"Under-charged","lines":[{"description":"Price correction","quantity":1.0,"unitPrice":200.0,"vatRate":15.0}],"clientId":"453b20f0-8fc1-50d0-9471-51761784522b"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"DN-4471","issueDate":"2026-09-30","billNumber":"INV-1"},"module":"expenses","plan":"Starter","scope":"expenses:write"},{"method":"GET","path":"/api/sars/vat-creditors?asOf=2026-09-30","summary":"Bills unpaid 12 months after the tax period of their deduction (s22(3)), and bills paid since their adjustment (s22(4)). Posts nothing.","auth":"jwt","responseExample":{"asOf":"text","unpaid":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","twelveMonthsEnd":"2026-09-30","adjustmentDate":"2026-09-01","amount":10005.0,"vatAmount":1305.0,"groupCompany":false}],"paidSince":[{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","twelveMonthsEnd":"2026-09-30","adjustmentDate":"2026-09-01","amount":10005.0,"vatAmount":1305.0,"groupCompany":false}]},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"GET","path":"/api/sars/vat-deregistration?date=2026-09-30","summary":"Draft the final VAT201 of a company whose VAT registration ends on `date` (the last day of the final tax period; default today). Lists the stock (open batch layers) and fixed assets still held with the s10(5) value of the s8(2) deemed supply - the lesser of cost including VAT and open market value - and the bills whose claimed VAT is still unpaid (s22(3)). Once recorded, answers the recorded date and reason. Posts nothing. Needs sars:view.","auth":"jwt","responseExample":{"effectiveDate":"2026-09-30","recorded":false,"reason":null,"stock":[{"kind":"stock","id":"7f6c1a2e-0000-4000-8000-000000000004","name":"Cup","costIncludingVat":3450.0,"openMarketValue":null,"value":3450.0,"vatAmount":450.0}],"assets":[{"kind":"asset","id":"7f6c1a2e-0000-4000-8000-000000000003","name":"Delivery bakkie","costIncludingVat":230000.0,"openMarketValue":115000.0,"value":115000.0,"vatAmount":15000.0}],"creditors":[{"billId":"7f6c1a2e-0000-4000-8000-000000000002","reference":"INV-0001","amount":1150.0,"vatAmount":150.0}],"stockValue":3450.0,"stockVat":450.0,"assetValue":115000.0,"assetVat":15000.0,"creditorVat":150.0},"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"POST","path":"/api/sars/vat-deregistration","summary":"Cancel the company's VAT registration with `effectiveDate` as its last day as a vendor, for `reason`. Dated that day, it posts the s8(2) deemed supply of the stock (VAT201 fields 1 and 4) and capital assets (1A and 4A) still held at the s10(5) value - `openMarketValues` maps an item id to a lower open market value - (DR 6345 / CR 2130), and the s22(3) output tax on each bill still unpaid. After the date the company charges and claims no VAT, prints no VAT number and is asked for no VAT201. Refused for a company that is not a vendor on the date, one already deregistered, or a blank reason. Needs sars:edit.","auth":"jwt","body":{"effectiveDate":"2026-09-30","reason":"Turnover below R1 million; SARS letter of 2026-09-15","openMarketValues":{"7f6c1a2e-0000-4000-8000-000000000003":115000.0}},"responseExample":{"effectiveDate":"2026-09-30","recorded":true,"reason":"Turnover below R1 million; SARS letter of 2026-09-15","stock":[{"kind":"stock","id":"7f6c1a2e-0000-4000-8000-000000000004","name":"Cup","costIncludingVat":3450.0,"openMarketValue":null,"value":3450.0,"vatAmount":450.0}],"assets":[{"kind":"asset","id":"7f6c1a2e-0000-4000-8000-000000000003","name":"Delivery bakkie","costIncludingVat":230000.0,"openMarketValue":115000.0,"value":115000.0,"vatAmount":15000.0}],"creditors":[{"billId":"7f6c1a2e-0000-4000-8000-000000000002","reference":"INV-0001","amount":1150.0,"vatAmount":150.0}],"stockValue":3450.0,"stockVat":450.0,"assetValue":115000.0,"assetVat":15000.0,"creditorVat":150.0},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"GET","path":"/api/sars/vat-filed-periods","summary":"The VAT periods noted as filed: dates only, for the prompt as a document is dated.","auth":"jwt","responseExample":[{"periodStart":"2026-09-01","periodEnd":"2026-09-30","periodLabel":"2026-09"}],"module":"vat-returns","plan":"Business","scope":"vat-returns:read"},{"method":"POST","path":"/api/sars/vat201/correction","summary":"Note that the correction of a filed period was submitted on eFiling. Ledgr transmits nothing; the prepared figures become the filed return.","auth":"jwt","body":{"periodStart":"2026-09-01","periodEnd":"2026-09-30","reference":"RFC 1"},"responseExample":{"noted":true},"module":"vat-returns","plan":"Business","scope":"vat-returns:write"},{"method":"POST","path":"/api/ledger/periods/generate","summary":"Make the twelve months of the financial year holding a date, skipping what exists.","auth":"jwt","body":{"date":"2026-09-30"},"responseExample":{"created":1},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/ledger/periods/lock-through","summary":"Lock every period up to and including a period end. Needs approve rights.","auth":"jwt","body":{"date":"2026-09-30"},"responseExample":{"locked":1},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/ledger/year-end-checklist?yearEnd=2027-02-28","summary":"What is done and what is open for a year end. Posts nothing.","auth":"jwt","responseExample":{"yearEnd":"2026-09-30","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","done":true,"detail":"Saved."}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/fixed-assets/{id}/impair","summary":"Record an impairment loss, or its reversal, on one asset, with the reason.","auth":"jwt","body":{"date":"2026-09-30","amount":30000.0,"reason":"Fire damage","reversal":false},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","assetClass":"text","assetClassLabel":"Karoo Fresh Holdings Ltd","acquisitionDate":"2026-09-01","cost":10005.0,"residualValue":10005.0,"usefulLifeMonths":1,"usefulLifeReliable":true,"method":"eft","ratePercent":15.0,"accumulatedDepreciation":1.0,"bookValue":10005.0,"depreciatedTo":"2026-09-30","status":"sent","disposalDate":"2026-09-01","disposalProceeds":1.0,"disposalOutputVat":1305.0,"serialNumber":"INV-0001","location":"text","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreCode":"CT-001","supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","monthsRemaining":1},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/loans?asAt=2026-10-31","summary":"The loan register at a date (today by default): each loan's terms, the capital still owed on its schedule, the interest accrued since the last instalment and the part due within twelve months, and the register's tie to each loan account and to the interest accrued.","auth":"jwt","responseExample":{"asAt":"2026-10-31","loans":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"ABSA term loan","lenderName":"ABSA Bank","accountCode":"2010","principal":240000.0,"annualRatePercent":11.0,"advanceDate":"2026-04-01","termMonths":24,"firstInstalmentDate":"2026-05-01","instalment":11185.88,"maturityDate":"2028-04-01","securityDescription":"a cession of book debts","outstanding":184833.96,"accruedInterest":1694.31,"currentPortion":119820.37,"nonCurrentPortion":65013.59,"accruedPeriodEnds":["2026-10-31"],"transactionCosts":4800.0,"marketRatePercent":null,"lenderIsOwner":false,"effectiveRatePercent":13.04,"initialCarryingAmount":235200.0,"dayOneDifference":0.0,"carryingAmount":182271.57}],"outstanding":184833.96,"accruedInterest":1694.31,"currentPortion":119820.37,"nonCurrentPortion":65013.59,"ties":[{"code":"LOAN-2010","name":"Loans: Long-term Loans (2010)","ledger":184833.96,"subledger":184833.96,"difference":0.0,"ties":true,"note":"The principal of the loans booked to 2010 less the capital of every instalment due by 2026-10-31 (the loan register's schedule)."}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/loans","summary":"Register a borrowing: the lender, the loan account it is booked to (2010 or 2020), the amount, the yearly rate, the advance date, the term in monthly instalments and the first instalment (the bank's stated instalment where it has one). The schedule is worked from these terms. Fees paid to arrange it and, for a loan below a market rate, that market rate carry it at amortised cost (IFRS for SMEs 11.13-11.20): a below-market loan's day-one difference is posted on the advance date, to equity when the lender is an owner, else to profit.","auth":"jwt","body":{"name":"ABSA term loan","lenderName":"ABSA Bank","accountCode":"2010","principal":240000.0,"annualRatePercent":11.0,"advanceDate":"2026-04-01","termMonths":24,"firstInstalmentDate":"2026-05-01","instalment":11185.88,"securityDescription":"a cession of book debts","transactionCosts":4800.0,"marketRatePercent":null,"lenderIsOwner":false},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"ABSA term loan","lenderName":"ABSA Bank","accountCode":"2010","principal":240000.0,"annualRatePercent":11.0,"advanceDate":"2026-04-01","termMonths":24,"firstInstalmentDate":"2026-05-01","instalment":11185.88,"maturityDate":"2028-04-01","securityDescription":"a cession of book debts","outstanding":184833.96,"accruedInterest":1694.31,"currentPortion":119820.37,"nonCurrentPortion":65013.59,"accruedPeriodEnds":["2026-10-31"],"transactionCosts":4800.0,"marketRatePercent":null,"lenderIsOwner":false,"effectiveRatePercent":13.04,"initialCarryingAmount":235200.0,"dayOneDifference":0.0,"carryingAmount":182271.57},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/loans/{id}/schedule","summary":"A loan's repayment schedule: each instalment's date, the interest and capital it pays, and what is owed after it.","auth":"jwt","responseExample":{"loanId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"ABSA term loan","rows":[{"number":7,"date":"2026-11-01","opening":184833.96,"interest":1694.31,"capital":9491.57,"payment":11185.88,"closing":175342.39,"effectiveInterest":1977.1,"carryingAmount":172780.0}]},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"DELETE","path":"/api/loans/{id}","summary":"Take a loan off the register. Refused (409) once interest has been accrued on it.","auth":"jwt","responseKind":"none","module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/loans/accrue?periodEnd=2026-10-31","summary":"Accrue each loan's interest to a period end that has arrived: DR 6330 / CR 2121, taken back the next morning because the instalment pays that interest; for a loan with fees or a below-market discount, also the part of them charged as interest at the effective rate to that date (DR 6330 / CR the loan account, not reversed). Once per loan and period end; a repeat run accrues nothing.","auth":"jwt","responseExample":{"periodEnd":"2026-10-31","accrued":[{"loanId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"ABSA term loan","interest":1694.31,"alreadyAccrued":false,"discountUnwound":2237.61}],"totalInterest":1694.31,"totalUnwound":2237.61},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/fixed-assets/deferred-tax?yearEnd=2027-02-28","summary":"Deferred tax on the register at a year end: book value against tax value at the company rate. Posts nothing.","auth":"jwt","responseExample":{"yearEnd":"2026-09-30","carryingAmount":10005.0,"taxValue":1305.0,"temporaryDifference":1.0,"ratePercent":15.0,"requiredBalance":10005.0,"bookedBalance":10005.0,"movement":1.0,"unmappedAssets":["text"],"declinedReason":"Budget deferred to the next financial year."},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"POST","path":"/api/fixed-assets/deferred-tax","summary":"Take the deferred tax account to the calculated balance at a year end.","auth":"jwt","body":{"yearEnd":"2027-02-28"},"responseExample":{"yearEnd":"2026-09-30","carryingAmount":10005.0,"taxValue":1305.0,"temporaryDifference":1.0,"ratePercent":15.0,"requiredBalance":10005.0,"bookedBalance":10005.0,"movement":1.0,"unmappedAssets":["text"],"declinedReason":"Budget deferred to the next financial year."},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/fixed-assets/deferred-tax/decline","summary":"Record the policy of not recognising deferred tax, with the reason. A blank reason clears it.","auth":"jwt","body":{"reason":"Micro entity policy"},"responseExample":{"declined":1},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"POST","path":"/api/contacts/contra","summary":"Set one bill against the invoices of the same party, oldest as listed, up to what is still owed on the bill: invoices that cover it settle it, invoices owing less part-pay it. Every invoice must be owed by the bill's own supplier contact, and a bill with no supplier contact is refused (409). Rand documents only, and no VAT moves.","auth":"jwt","body":{"billId":"7f6c1a2e-0000-4000-8000-000000000001","invoiceIds":["7f6c1a2e-0000-4000-8000-000000000002"],"date":"2026-09-30","reason":"Offset agreed"},"responseExample":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"invoices":["text"]},"module":"contacts","plan":"Free","scope":"contacts:write"},{"method":"GET","path":"/api/sars/it14?year=2027","summary":"The company income tax estimate for a fiscal year.","auth":"jwt","responseExample":{"taxYearLabel":"2027","periodStart":"2026-09-01","periodEnd":"2026-09-30","revenue":1.0,"expenses":1.0,"taxableIncome":1305.0,"taxAt27":1305.0,"provisionalPaid":1.0,"balanceDue":10005.0,"estimate":true,"returnCode":"CT-001","returnTitle":"Karoo Fresh Holdings Ltd","dueDate":"2026-09-01","dueDateLabel":"2026-09-01","reconciliation":[{"label":"Karoo Fresh Holdings Ltd","amount":10005.0,"subtotal":false}],"netProfitBeforeTax":1305.0,"depreciationAddedBack":1.0,"wearAndTear":1.0,"assessedLossApplies":true,"assessedLossBroughtForward":1.0,"assessedLossSource":"referral","assessedLossLimit":1.0,"assessedLossSetOff":1.0,"assessedLossCarriedForward":1.0,"donationsCharged":1.0,"donationReceiptsHeld":1.0,"donationsWithoutReceipt":0.0,"issues":[],"wearAndTearIssues":["The control account and the age analysis differ by R0.00."]},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"PUT","path":"/api/sars/itr14/assessed-loss","summary":"Record the balance of assessed loss brought forward into an ITR14 year, from your last SARS assessment. `yearEnd` is the last day of the financial year it is brought into; R0.00 records that the assessment shows none. It replaces the balance Ledgr would otherwise carry from its own computation of the previous year. The set-off is limited, for years ending on or after 31 March 2023, to the greater of R1 000 000 and 80% of taxable income before it. Answers with that year's estimate and its reconciliation. Needs sars:edit.","auth":"jwt","body":{"yearEnd":"2027-02-28","amount":30000.0},"responseExample":{"taxYearLabel":"2027","periodStart":"2026-03-01","periodEnd":"2027-02-28","revenue":500000.0,"expenses":60000.0,"taxableIncome":370000.0,"taxAt27":99900.0,"provisionalPaid":0.0,"balanceDue":99900.0,"estimate":true,"returnCode":"ITR14","returnTitle":"Company Income Tax Return (ITR14)","reconciliation":[{"label":"Net profit before tax per the income statement","amount":440000.0},{"label":"Add back: depreciation and amortisation","amount":10000.0},{"label":"Less: wear-and-tear, section 11(e)","amount":-50000.0},{"label":"Taxable income before the assessed loss","amount":400000.0},{"label":"Less: assessed loss set off, section 20","amount":-30000.0},{"label":"Taxable income per Ledgr","amount":370000.0}],"netProfitBeforeTax":440000.0,"depreciationAddedBack":10000.0,"wearAndTear":50000.0,"assessedLossApplies":true,"assessedLossBroughtForward":30000.0,"assessedLossSource":"typed","assessedLossLimit":1000000.0,"assessedLossSetOff":30000.0,"assessedLossCarriedForward":0.0,"donationsCharged":0.0,"donationReceiptsHeld":null,"donationsWithoutReceipt":0.0,"issues":[]},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"PUT","path":"/api/sars/itr14/donation-receipts","summary":"Record the value of the section 18A receipts you hold for an ITR14 year's donations. `yearEnd` is the last day of the financial year the donations were made in; R0.00 records that there are none. A donation is deductible only against a section 18A receipt (Income Tax Act s18A(2)), so until this is entered no donation is deducted, and the part of the year's donations no receipt supports is added back and not carried forward. The receipted part is deducted to 10% of taxable income. Answers with that year's estimate and its reconciliation. Needs sars:edit.","auth":"jwt","body":{"yearEnd":"2027-02-28","amount":10000.0},"responseExample":{"taxYearLabel":"2027","periodStart":"2026-03-01","periodEnd":"2027-02-28","revenue":2000000.0,"expenses":1660000.0,"taxableIncome":360000.0,"taxAt27":97200.0,"provisionalPaid":0.0,"balanceDue":97200.0,"taxNotStated":null,"estimate":true,"returnCode":"ITR14","returnTitle":"Company Income Tax Return (ITR14)","dueDate":"2028-02-28","dueDateLabel":"Within 12 months of the year end","reconciliation":[{"label":"Net profit before tax per the income statement","amount":340000.0,"subtotal":false},{"label":"Add back: donations without a section 18A receipt (section 18A(2))","amount":20000.0,"subtotal":false},{"label":"Taxable income before the assessed loss","amount":360000.0,"subtotal":false},{"label":"Less: assessed loss set off, section 20","amount":0.0,"subtotal":false},{"label":"Taxable income per Ledgr","amount":360000.0,"subtotal":false}],"netProfitBeforeTax":340000.0,"depreciationAddedBack":0.0,"wearAndTear":0.0,"assessedLossApplies":true,"assessedLossBroughtForward":0.0,"assessedLossSource":null,"assessedLossLimit":null,"assessedLossSetOff":0.0,"assessedLossCarriedForward":0.0,"donationsCharged":30000.0,"donationReceiptsHeld":10000.0,"donationsWithoutReceipt":20000.0,"issues":[],"wearAndTearIssues":[]},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/it14/current-tax?year=2027","summary":"The year's income tax as the books hold it (IFRS for SMEs 29.5): the ITR14's normal tax, what was paid to SARS, the income tax expense already in the books, the charge still to post (DR Income Tax Expense 6910 / CR Income Tax Payable 2170) and the payable at the year end. Posts nothing. A sole proprietor or a partnership pays no tax of the business's own, and a return that states no tax, so `notProposed` says why. Needs sars:view.","auth":"jwt","responseExample":{"yearEnd":"2027-02-28","normalTax":270000.0,"paidToSars":200000.0,"charged":0.0,"movement":270000.0,"payable":-200000.0},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/it14/current-tax","summary":"Post the year's income tax: DR Income Tax Expense (6910) / CR Income Tax Payable (2170) for the ITR14's normal tax not yet charged, dated the year end. A payment to SARS is DR 2170, so the payable ends at the tax still owed (a debit is tax paid ahead). Posts once per year end: a second post posts only a change in the tax. Refused when the business is not taxed on its own return or the return states no tax. Needs sars:approve.","auth":"jwt","body":{"year":2027},"responseExample":{"yearEnd":"2027-02-28","normalTax":270000.0,"paidToSars":200000.0,"charged":270000.0,"movement":0.0,"payable":70000.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"POST","path":"/api/sars/it14/submit","summary":"Note the ITR14 as filed.","auth":"jwt","body":{"year":2027},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars/irp6?year=2027&period=2&basis=annualised&estimate=150000","summary":"The provisional tax estimate for a period (1, 2, or 3 for the voluntary top-up after year end). `estimate` is the taxable income you mean to file (default: the prepared figure); the first period warns when the estimate is below the basic amount (para 19(1)(c)); the second period is tested as SARS will test it, against the basic amount and 90% (80% above R1 million) of the year as projected, with the required minimum and the estimated under-estimation penalty (20% of the tax on the minimum less the tax paid to SARS by the year end). `alreadyPaid` is money paid to SARS, not IRP6s noted as filed.","auth":"jwt","responseExample":{"taxYearLabel":"2027","periodNumber":1,"periodStart":"2026-09-01","periodEnd":"2026-09-30","taxableIncomeToDate":1305.0,"estimatedAnnualTaxableIncome":1305.0,"estimatedAnnualTax":1305.0,"alreadyPaid":1.0,"periodPayment":1.0,"estimate":true},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars/irp6/submit","summary":"Note the IRP6 as filed — period 1, 2 or 3 (the voluntary top-up), on the taxable income in `estimate` (default: the prepared figure).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"body":{"year":2027,"period":1,"basis":"invoice","estimate":150000.0},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"PUT","path":"/api/sars/irp6/basic-amount","summary":"Record the IRP6 basic amount for a year of assessment: the taxable income on your latest SARS assessment, and which year that assessment was for. The second-period under-estimation test reads it. Answers with that year's second-period estimate. Needs sars:edit.","auth":"jwt","body":{"year":2027,"basicAmount":200000.0,"assessedYear":2026},"responseExample":{"taxYearLabel":"2027","periodNumber":2,"periodStart":"2026-03-01","periodEnd":"2027-02-28","taxableIncomeToDate":87500.0,"estimatedAnnualTaxableIncome":150000.0,"estimatedAnnualTax":40500.0,"alreadyPaid":0.0,"periodPayment":40500.0,"estimate":true,"basis":"annualised","basicAmount":200000.0,"basicAmountAssessedYear":2026,"filedEstimate":150000.0,"requiredMinimum":135000.0,"testName":"ninety_percent_or_basic","passesTest":true,"estimatedPenalty":0.0,"issues":[]},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars-submissions?type=vat201&status=filed","summary":"The filing register across every tax type.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}],"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"POST","path":"/api/sars-submissions","summary":"Add a filing record by hand.","auth":"jwt","body":{"submissionType":"VAT201","periodStart":"2026-07-01","periodEnd":"2026-08-31"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars-submissions/{id}","summary":"One filing record.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"PUT","path":"/api/sars-submissions/{id}","summary":"Correct a filing record.","auth":"jwt","body":{"submissionType":"VAT201","periodStart":"2026-07-01","periodEnd":"2026-08-31"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"POST","path":"/api/sars-submissions/{id}/submit","summary":"Mark a prepared return as filed. Optionally keep what eFiling issued: sarsReference, filedOn, and the payment (paidOn with paidAmount); a date before the period ended or in the future is refused (400).","auth":"jwt","body":{"paymentReferenceNumber":"7012345676LC2609000","sarsReference":"EFL-2026-0007","filedOn":"2026-09-03","paidOn":"2026-09-03","paidAmount":13852.72},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"PUT","path":"/api/sars-submissions/{id}/payment-reference","summary":"Record the payment reference number SARS issued for a filed EMP201.","auth":"jwt","body":{"paymentReferenceNumber":"7012345676LC2609000"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"PUT","path":"/api/sars-submissions/{id}/filing-details","summary":"Keep what eFiling issued for a return already noted as filed: SARS's reference, the day it was filed, and the payment (paidOn with paidAmount). Replaces the four; a blank part clears it. A date before the period ended or in the future is refused (400); a return not yet filed is refused (409).","auth":"jwt","body":{"sarsReference":"EFL-2026-0007","filedOn":"2026-09-03","paidOn":"2026-09-03","paidAmount":13852.72},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":13852.72,"totalDue":13852.72,"status":"sent","referenceNumber":"INV-0001","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z","sarsReference":"EFL-2026-0007","filedOn":"2026-09-03","paidOn":"2026-09-03","paidAmount":13852.72},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"POST","path":"/api/sars-submissions/{id}/correction","summary":"Note the request for correction (RFC) of a filed EMP201: the filed row takes the payslips' figures and the old ones are kept.","auth":"jwt","body":{"reference":"RFC-2026-0912"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submissionType":"EMP201","periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12900.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalPayable":14352.72,"totalDue":14352.72,"status":"sent","referenceNumber":"INV-0001","paymentReferenceNumber":"7012345676LC2609000","submittedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"sars","plan":"Professional","scope":"sars:write"},{"method":"GET","path":"/api/sars-submissions/emp201/{periodId}","summary":"The EMP201 figures for a payroll period.","auth":"jwt","responseExample":{"periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalEtiCalculated":10005.0,"payeAfterEti":1.0,"totalPayable":13852.72,"employeeCount":3,"lines":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","paye":1.0,"uif":1.0,"sdl":1.0}]},"module":"sars","plan":"Professional","scope":"sars:read"},{"method":"GET","path":"/api/sars-submissions/emp501?taxYear=2027","summary":"The EMP501 reconciliation figures.","auth":"jwt","responseExample":{"taxYear":"2027","months":[{"month":"2026-09","paye":1.0,"uif":1.0,"sdl":1.0,"eti":1.0,"total":10005.0,"paid":1.0}],"interimPaye":1.0,"interimUif":1.0,"interimSdl":1.0,"interimEti":1.0,"interimTotal":10005.0,"interimPaid":1.0,"annualPaye":1.0,"annualUif":1.0,"annualSdl":1.0,"annualEti":1.0,"annualTotal":10005.0,"annualPaid":1.0},"module":"sars","plan":"Professional","scope":"sars:read"}]},{"name":"Payroll","blurb":"SARS PAYE keyed by year of assessment — 2022/23 to 2026/27 registered, an unsupported year is REFUSED rather than served from the nearest one. Part-year employment follows Fourth Schedule paras 9(1)/9(2): annualise to find the rate, then pro-rate by periods WORKED.","endpoints":[{"method":"GET","path":"/api/employees?search=cape&includeLeavers=true","summary":"Employees with their statutory fields.","auth":"jwt","responseExample":[{"documentLanguage":"text","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","idNumber":"INV-0001","passportNumber":"INV-0001","passportCountry":"South Africa","addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","postalCode":"CT-001","addressCountry":"South Africa","asylumPermitNumber":"INV-0001","natureOfPerson":"text","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","dateOfBirth":"1988-04-12","employmentType":"standard","contractorWorksAtPremises":true,"contractorIsSupervised":true,"contractorHasThreeEmployees":true,"contractorNonResident":true,"irp30Number":"INV-0001","irp30ValidTo":"2026-09-30","pspRegistrationType":"standard","pspRegistrationNumber":"2021/123456/07","noOtherEmployerDeclaration":true,"startDate":"2026-09-01","endDate":"2026-09-30","terminationReason":"Budget deferred to the next financial year.","terminated":false,"jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","bankAccountType":"current","paymentMethod":"eft","secondBankName":"FNB","secondBankAccountNumber":"62012345678","secondBankBranchCode":"250655","secondBankAccountType":"standard","splitAmount":10005.0,"splitPercent":15.0,"minimumWageExemption":"text","minimumWageExemptionUntil":"2026-09-30","learnershipRegistrationNumber":"2021/123456/07","learnershipNqfLevel":1,"learnershipStart":"2026-09-01","learnershipEnd":"2026-09-30","learnershipDisability":true,"learnershipCompletedOn":"2026-09-01","learnershipCreditsEarned":1,"epwpWorker":true,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"MONTHLY","basicSalary":1.0,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"leaveBalances":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","balanceDays":10005.0,"takenDays":1.0}],"leaveDaysPerWeek":5,"leaveWorksSundays":false,"leaveWeekdays":[1,2,3,4,5],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/employees","summary":"Create an employee. default_charge_rate and default_cost_rate live on the user record and fill in job-card labour — null means \"not set\" rather than zero, and the reports say so rather than showing a flattering 100% margin.","auth":"jwt","body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","firstName":"Thandi","lastName":"Mokoena","idNumber":"INV-0001","dateOfBirth":"1988-04-12","employmentType":"PERMANENT","contractorWorksAtPremises":null,"contractorIsSupervised":null,"contractorHasThreeEmployees":null,"contractorNonResident":null,"irp30Number":null,"irp30ValidTo":null,"pspRegistrationType":null,"pspRegistrationNumber":null,"noOtherEmployerDeclaration":false,"startDate":"2026-09-01","endDate":"2026-09-30","jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankAccountNumber":"62012345678","bankName":"FNB","bankBranchCode":"250655","bankAccountType":"current","paymentMethod":"SPLIT","secondBankName":"Capitec","secondBankAccountNumber":"1234567890","secondBankBranchCode":"470010","secondBankAccountType":"savings","splitAmount":1000.0,"splitPercent":null,"learnershipRegistrationNumber":null,"learnershipNqfLevel":null,"learnershipStart":null,"learnershipEnd":null,"learnershipDisability":false,"learnershipCompletedOn":null,"learnershipCreditsEarned":null,"epwpWorker":false,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"MONTHLY","basicSalary":1.0,"payBasis":"salary","hourlyRate":15.0,"payTemplateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":5,"ordinaryWeekdays":[1,2,3,4,5],"ordinarilyWorksSundays":false,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"natureOfPerson":"A","passportNumber":"INV-0001","passportCountry":"South Africa","addressLine1":"4 Kloof Street","addressLine2":"Tamboerskloof","city":"Cape Town","postalCode":"8001","addressCountry":"ZA","asylumPermitNumber":"CTRIMO001232019","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","etiExclusion":"Connected person to the employer","etiMinimumWageMonthly":1.0,"etiNoWageRegulatingMeasure":false,"etiMonthsClaimedBeforeLedgr":1,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"minimumWageExemption":"NMW-EX-2026-014","minimumWageExemptionUntil":"2027-02-28","documentLanguage":"af"},"responseExample":{"documentLanguage":"text","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","idNumber":"INV-0001","passportNumber":"INV-0001","passportCountry":"South Africa","addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","postalCode":"CT-001","addressCountry":"South Africa","asylumPermitNumber":"INV-0001","natureOfPerson":"text","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","dateOfBirth":"1988-04-12","employmentType":"standard","contractorWorksAtPremises":true,"contractorIsSupervised":true,"contractorHasThreeEmployees":true,"contractorNonResident":true,"irp30Number":"INV-0001","irp30ValidTo":"2026-09-30","pspRegistrationType":"standard","pspRegistrationNumber":"2021/123456/07","noOtherEmployerDeclaration":true,"startDate":"2026-09-01","endDate":"2026-09-30","terminationReason":"Budget deferred to the next financial year.","terminated":false,"jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","bankAccountType":"current","paymentMethod":"eft","secondBankName":"FNB","secondBankAccountNumber":"62012345678","secondBankBranchCode":"250655","secondBankAccountType":"standard","splitAmount":10005.0,"splitPercent":15.0,"minimumWageExemption":"text","minimumWageExemptionUntil":"2026-09-30","learnershipRegistrationNumber":"2021/123456/07","learnershipNqfLevel":1,"learnershipStart":"2026-09-01","learnershipEnd":"2026-09-30","learnershipDisability":true,"learnershipCompletedOn":"2026-09-01","learnershipCreditsEarned":1,"epwpWorker":true,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"MONTHLY","basicSalary":1.0,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"leaveBalances":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","balanceDays":10005.0,"takenDays":1.0}],"leaveDaysPerWeek":5,"leaveWorksSundays":false,"leaveWeekdays":[1,2,3,4,5],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/employees/{id}","summary":"One employee.","auth":"jwt","responseExample":{"documentLanguage":"text","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","idNumber":"INV-0001","passportNumber":"INV-0001","passportCountry":"South Africa","addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","postalCode":"CT-001","addressCountry":"South Africa","asylumPermitNumber":"INV-0001","natureOfPerson":"text","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","dateOfBirth":"1988-04-12","employmentType":"standard","contractorWorksAtPremises":true,"contractorIsSupervised":true,"contractorHasThreeEmployees":true,"contractorNonResident":true,"irp30Number":"INV-0001","irp30ValidTo":"2026-09-30","pspRegistrationType":"standard","pspRegistrationNumber":"2021/123456/07","noOtherEmployerDeclaration":true,"startDate":"2026-09-01","endDate":"2026-09-30","terminationReason":"Budget deferred to the next financial year.","terminated":false,"jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","bankAccountType":"current","paymentMethod":"eft","secondBankName":"FNB","secondBankAccountNumber":"62012345678","secondBankBranchCode":"250655","secondBankAccountType":"standard","splitAmount":10005.0,"splitPercent":15.0,"minimumWageExemption":"text","minimumWageExemptionUntil":"2026-09-30","learnershipRegistrationNumber":"2021/123456/07","learnershipNqfLevel":1,"learnershipStart":"2026-09-01","learnershipEnd":"2026-09-30","learnershipDisability":true,"learnershipCompletedOn":"2026-09-01","learnershipCreditsEarned":1,"epwpWorker":true,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"MONTHLY","basicSalary":1.0,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"leaveBalances":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","balanceDays":10005.0,"takenDays":1.0}],"leaveDaysPerWeek":5,"leaveWorksSundays":false,"leaveWeekdays":[1,2,3,4,5],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/employees/{id}","summary":"Update an employee.","auth":"jwt","body":{"addressLine1":"4 Kloof Street","addressLine2":"Tamboerskloof","city":"Cape Town","postalCode":"8001","addressCountry":"ZA","asylumPermitNumber":"CTRIMO001232019","firstName":"Thandi","lastName":"Mokoena","idNumber":"8506155009085","employeeNumber":"EMP-0042","startDate":"2026-03-01","dateOfBirth":"1985-06-15","payBasis":"salary","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employmentType":"standard","contractorWorksAtPremises":null,"contractorIsSupervised":null,"contractorHasThreeEmployees":null,"contractorNonResident":null,"irp30Number":null,"irp30ValidTo":null,"pspRegistrationType":null,"pspRegistrationNumber":null,"noOtherEmployerDeclaration":null,"endDate":"2026-09-30","terminationReason":"Budget deferred to the next financial year.","jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankAccountNumber":"62012345678","bankName":"FNB","bankBranchCode":"250655","bankAccountType":"standard","paymentMethod":"SPLIT","secondBankName":"Capitec","secondBankAccountNumber":"1234567890","secondBankBranchCode":"470010","secondBankAccountType":"savings","splitAmount":1000.0,"splitPercent":null,"learnershipRegistrationNumber":null,"learnershipNqfLevel":null,"learnershipStart":null,"learnershipEnd":null,"learnershipDisability":false,"learnershipCompletedOn":null,"learnershipCreditsEarned":null,"epwpWorker":false,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"monthly","basicSalary":1.0,"hourlyRate":15.0,"payTemplateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":5,"ordinaryWeekdays":[1,2,3,4,5],"ordinarilyWorksSundays":false,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"natureOfPerson":"A","passportNumber":"INV-0001","passportCountry":"South Africa","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","etiExclusion":"Connected person to the employer","etiMinimumWageMonthly":1.0,"etiNoWageRegulatingMeasure":true,"etiMonthsClaimedBeforeLedgr":1,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"minimumWageExemption":"NMW-EX-2026-014","minimumWageExemptionUntil":"2027-02-28","basicEffectiveFrom":"2026-03-01","documentLanguage":"af"},"responseExample":{"documentLanguage":"text","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","firstName":"Karoo Fresh Holdings Ltd","lastName":"Karoo Fresh Holdings Ltd","idNumber":"INV-0001","passportNumber":"INV-0001","passportCountry":"South Africa","addressLine1":"12 Long Street","addressLine2":"Woodstock","city":"Cape Town","postalCode":"CT-001","addressCountry":"South Africa","asylumPermitNumber":"INV-0001","natureOfPerson":"text","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","dateOfBirth":"1988-04-12","employmentType":"standard","contractorWorksAtPremises":true,"contractorIsSupervised":true,"contractorHasThreeEmployees":true,"contractorNonResident":true,"irp30Number":"INV-0001","irp30ValidTo":"2026-09-30","pspRegistrationType":"standard","pspRegistrationNumber":"2021/123456/07","noOtherEmployerDeclaration":true,"startDate":"2026-09-01","endDate":"2026-09-30","terminationReason":"Budget deferred to the next financial year.","terminated":false,"jobTitle":"Karoo Fresh Holdings Ltd","department":"Sales","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","bankAccountType":"current","paymentMethod":"eft","secondBankName":"FNB","secondBankAccountNumber":"62012345678","secondBankBranchCode":"250655","secondBankAccountType":"standard","splitAmount":10005.0,"splitPercent":15.0,"minimumWageExemption":"text","minimumWageExemptionUntil":"2026-09-30","learnershipRegistrationNumber":"2021/123456/07","learnershipNqfLevel":1,"learnershipStart":"2026-09-01","learnershipEnd":"2026-09-30","learnershipDisability":true,"learnershipCompletedOn":"2026-09-01","learnershipCreditsEarned":1,"epwpWorker":true,"prescribedOfficer":false,"taxNumber":"9012345678","uifLiable":true,"payFrequency":"MONTHLY","basicSalary":1.0,"travelAllowance":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"medicalAidMembers":1,"travelInclusionRate":15.0,"openingYtdTaxYearEnd":1,"openingYtdRemuneration":1.0,"openingYtdPaye":1.0,"openingYtdAnnualPayments":1.0,"openingYtdPayeOnAnnualPayments":1.0,"leaveBalances":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","balanceDays":10005.0,"takenDays":1.0}],"leaveDaysPerWeek":5,"leaveWorksSundays":false,"leaveWeekdays":[1,2,3,4,5],"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/employees/{id}?reason=Duplicate&endDate=2027-02-28&capturedInError=false&notice=worked","summary":"Terminate an employee: ends the employment on endDate and keeps the record, so the final month is paid to the last day and owed annual leave is paid out; notice=paid pays the notice period in lieu (BCEA s38), and a retrenchment adds severance taxed by its lump-sum directive. With capturedInError=true the record is deleted instead, refused once any payslip exists.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/employees/{id}/payslips","summary":"One employee's payslip history.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","payDate":"2026-09-01","basicSalary":1.0,"travelAllowance":1.0,"overtime":1.0,"commission":1.0,"bonus":1.0,"otherAllowances":1.0,"grossSalary":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"employerRetirement":1.0,"employerMedical":1.0,"thirdPartyDeductions":1.0,"taxableRemuneration":1305.0,"travelInclusionRate":15.0,"payeTax":1305.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"netPay":8700.0,"ytdGross":1.0,"ytdPaye":1.0,"hoursWorked":3.0,"etiHoursSource":"referral","etiAmount":10005.0,"etiReason":"Budget deferred to the next financial year.","catchUpPaye":1.0,"catchUpNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","deductionLines":[{"beneficiaryName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","employeeAmount":10005.0,"employerAmount":10005.0}],"fringeBenefitsOtherRemuneration":1.0,"status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/employees/{id}/leave-balances","summary":"BCEA balances — 15 days annual, 30 days sick over a three-year cycle, three days family responsibility.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","balanceDays":10005.0,"takenDays":1.0}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/employees/{id}/irp5?taxYear=2027","summary":"One employee's IRP5 as data. payPeriodsWorked is code 3210 as the certificate states it, a part period as its fraction (6.5 for a leaver of 15 September); monthsWorked is the same count rounded to a whole number and is kept only for compatibility.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","employeeNumber":"INV-0001","taxNumber":"9012345678","idNumber":"INV-0001","taxYear":"2027","certificateNumber":"INV-0001","certificateType":"standard","grossRemuneration":1.0,"payeDeducted":1.0,"uifTotal":10005.0,"sdl":1.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"providentTotal":10005.0,"retirementAnnuityTotal":10005.0,"medicalTaxCredit":1305.0,"additionalMedicalCredit":1.0,"severanceBenefit":1.0,"lumpSumTax":1305.0,"eti":1.0,"totalTaxSdlUif":1305.0,"employerRetirementBenefit":1.0,"employerMedicalBenefit":1.0,"monthsWorked":1,"payPeriodsWorked":1.0,"periodsInYear":12,"takeOnIncluded":false,"takeOnGrossRemuneration":1.0,"takeOnPaye":1.0,"takeOnSourceLabel":"Karoo Fresh Holdings Ltd"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/employees/{id}/irp5.pdf?taxYear=2027","summary":"The same certificate as a PDF - or, until it may be delivered (the year's annual EMP501 noted as filed, or the employee left in it), a tax-year-to-date statement with no certificate number. For an employee ended as deceased it is headed as issued to the executor of the estate, who is owed it within 14 days of the death.","auth":"jwt","responseKind":"pdf","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll-periods","summary":"Payroll periods and their state.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll-periods","summary":"Open a period.","auth":"jwt","body":{"periodType":"MONTHLY","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-25"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll-periods/{id}","summary":"One period with its totals.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll-periods/{id}","summary":"Change a period's dates before it is run.","auth":"jwt","body":{"periodType":"MONTHLY","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-26"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll-periods/{id}","summary":"Delete an unrun period.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/run","summary":"Calculate the period — PAYE, UIF at 1% capped at R177.12 each side, SDL at 1%, ETI, deductions and fringe benefits.","auth":"jwt","responseExample":{"period":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"payslipsCreated":1,"alreadyRun":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll-periods/{id}/inputs?employeeId=8b2d1e44-0c9a-4f71-b6de-5a3c2f1e9d07&page=1&limit=200","summary":"The period's pay inputs — units and one-off amounts typed or fed for each employee and earning type — a page at a time (`page`, `limit`, optional `employeeId`). `editable` is false once the run is approved or paid.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}],"total":42,"page":1,"limit":50,"totalPages":1,"editable":true},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll-periods/{id}/inputs","summary":"Hold manual pay inputs for the period: units for a per-unit earning, an amount for a fixed one, both null to clear. A re-run of the period pays them. Refused with 409 once the run is approved or paid.","auth":"jwt","body":{"inputs":[{"employeeId":"8b2d1e44-0c9a-4f71-b6de-5a3c2f1e9d07","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","units":5.0,"note":"Night shifts, week 2","weekStart":"2026-09-07"}]},"responseExample":{"written":1,"cleared":1,"inputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/inputs/pull/logistics","summary":"Pull from Logistics: every run completed within the period, in South African time and in the period's company, credited as hours worked to the driver and the assistant through their payroll links — Sunday and public-holiday hours as their own kinds. Idempotent: a second pull holds what Logistics says now. `skipped` names what could not be counted. Refused with 409 once the run is approved or paid.","auth":"jwt","responseExample":{"source":"referral","counted":3,"people":1,"hours":3.0,"skipped":["text"],"removed":0,"inputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/inputs/pull/time","summary":"Pull from Time Tracking: every approved time entry whose work date falls in the period, credited as ordinary hours to the employee its user is linked to in the period's company. A billed hour is still paid. Idempotent; an entry un-approved since the last pull is taken off and counted in `removed`. A user on two companies' payrolls, or on none, is named in `skipped` and not counted. Refused with 409 once the run is approved or paid.","auth":"jwt","responseExample":{"source":"time","counted":3,"people":1,"hours":3.0,"skipped":["text"],"removed":0,"inputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/inputs/pull/shift","summary":"Pull from the shift register: every shift whose day falls in the period, as hours in the category its date says (Sunday, public holiday on an ordinary day or not, else normal) for the run to settle by the week, plus one unit of each per-unit allowance the shift earns. Idempotent; a shift deleted since the last pull is taken off and counted in `removed`. Refused with 409 once the run is approved or paid.","auth":"jwt","responseExample":{"source":"shift","counted":3,"people":1,"hours":3.0,"skipped":["text"],"removed":0,"inputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/shift-register?from=2026-09-01&to=2026-09-30&employeeId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The shift register for a window of at most 62 days, optionally one employee: each day worked, its hours, the category its date is paid in and the allowances it earns.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","workDate":"2026-09-24","hours":12.0,"category":"ph_worked_ordinary_day","allowanceTypeIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"note":"Night shift at the Midrand site."}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll/shift-register","summary":"Record one employee's day: hours (more than 0, at most 24) and the per-unit allowances the shift earns. Saving the same day again replaces it. Refused for a day the employee is not employed on, or an allowance that is not one of the tenant's per-unit earnings.","auth":"jwt","body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workDate":"2026-09-24","hours":12.0,"allowanceTypeIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"note":"Night shift at the Midrand site."},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","workDate":"2026-09-24","hours":12.0,"category":"ph_worked_ordinary_day","allowanceTypeIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"note":"Night shift at the Midrand site."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/shift-register/{id}","summary":"Remove a shift from the register. A period already pulled loses it on its next pull.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/employees/{id}/equity","summary":"An employee's Employment Equity categories — race, gender, disability, nationality and occupational level, each one of the EEA2's own; null is not recorded. Special personal information (POPIA s26): needs equity:view, which payroll:view does not grant, and every read is written to the audit log by who and which employee, never the values.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","race":"text","gender":"text","disabled":false,"foreignNational":false,"occupationalLevel":"text","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/employees/{id}/equity","summary":"Record an employee's Employment Equity categories (equity:edit). A category outside the Act's is refused; the change is audited by field name only.","auth":"jwt","body":{"race":"african","gender":"female","disabled":false,"foreignNational":false,"occupationalLevel":"skilled"},"responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","race":"text","gender":"text","disabled":false,"foreignNational":false,"occupationalLevel":"text","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/reports/employment-equity?form=eea2&periodEnd=2026-09-30&format=json","summary":"The Employment Equity report for the reporting period ending on the last 31 August on or before periodEnd: form eea2 (workforce profile by occupational level, race and gender, and for people with disabilities), eea4 (the period's remuneration in the same grid) or wsp-atr (the skills plan's employment profile by age band, and the year's SDL). The EEA4 and WSP/ATR also need payroll:view. Anybody without a level, gender or race recorded is listed in notCounted, never put in a guessed cell.","auth":"jwt","responseKind":"json","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/reports/employment-equity?form=eea4&periodEnd=2026-09-30&format=csv","summary":"The same report as CSV, table by table, to key into the Department of Employment and Labour's online system.","auth":"jwt","responseKind":"csv","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/shift-register/import","summary":"Import a clock's CSV export onto the register: a header row naming the employee (payroll number or ID number), the date, and the hours or In and Out times. One row per person per day — several clockings on a day are added up, a shift past midnight belongs to the day it started. Importing the same file again changes nothing; a corrected file changes only the days it corrects. Employee numbers nobody on the payroll holds, days outside a person's employment and lines that cannot be read are named, never guessed.","auth":"jwt","body":{"csv":"Employee Number,Name,Date,In,Out\nG-1,Lindiwe Roster,2026-09-14,06:00,18:00\n"},"responseExample":{"added":1,"updated":1,"unchanged":1,"unknown":["text"],"notEmployed":["text"],"refused":["text"]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/inputs/pull/jobs","summary":"Pull from Job Cards: every labour line counted in units (bays) whose work date falls in the period, on a completed or invoiced job in the period's company, credited as units of the earning type the line names to the employee its technician is linked to — paid at that person's rate. The work date, not the completion date, which a re-completed job overwrites. Idempotent; a line no longer counted is taken off and counted in `removed`. A line with no earning type, or a technician not on this payroll, is named in `skipped`. Refused with 409 once the run is approved or paid.","auth":"jwt","responseExample":{"source":"job","counted":3,"people":1,"hours":3.0,"skipped":["text"],"removed":0,"inputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","units":1.0,"amount":10005.0,"sourceKind":"standard","sourceRef":"INV-0001","note":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/preview","summary":"What a run of the period would produce now, saving nothing — the run itself in a transaction that is rolled back, so the figures are the run's own.","auth":"jwt","responseExample":{"periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locked":false,"payslips":[{"employeeId":"8b2d1e44-0c9a-4f71-b6de-5a3c2f1e9d07","gross":9500.0,"taxableRemuneration":9500.0,"paye":360.0,"uifEmployee":95.0,"uifEmployer":95.0,"sdl":0.0,"thirdPartyDeductions":95.0,"netPay":8950.0,"etiAmount":0.0,"fringeBenefits":0.0,"pension":0.0,"medical":0.0}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/periods/{periodId}/register?format=csv","summary":"The run's payroll register: a row per payslip, a column per line, the totals (which tie to the payroll journal), and the bank changes since the last approved run. ?format=csv or pdf to download.","auth":"jwt","responseKind":"csv","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/periods/{periodId}/variance","summary":"Every line that moved since the run before, per employee, with the reason: a new hire, a leaver, a basic salary, a pay input, or the arithmetic.","auth":"jwt","responseExample":{"periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","previousPeriodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","previousLabel":"Overtime","lines":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","column":"text","columnLabel":"Overtime","previous":1.0,"current":1.0,"change":1.0,"reason":"Budget deferred to the next financial year."}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/ytd?taxYear=2027","summary":"Year to date by employee from approved and paid runs; taxYear is the year the tax year ends in.","auth":"jwt","responseExample":{"taxYear":2026,"rows":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","costCentre":"text","amounts":{"key":10005.0}}],"totals":{"key":10005.0}},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/periods/{periodId}/cost-to-company","summary":"Cost to company for the run, by employee and by cost centre.","auth":"jwt","responseExample":{"periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","byEmployee":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","costCentre":"text","amounts":{"key":10005.0}}],"byCostCentre":{"key":10005.0},"total":10005.0},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/council-schedules","summary":"The bargaining-council schedules Ledgr has published, oldest first: grades by area, allowances and their minimums, levies and the rules, each cited. A pay template follows one by its council, grade and area.","auth":"jwt","responseExample":[{"council":"text","label":"Karoo Fresh Holdings Ltd","effectiveFrom":"2026-09-01","hourlyDivisor":1.0,"grades":[{"code":"CT-001","area":"text","monthlySalary":1.0}],"allowances":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","minimum":1.0,"per":"text"}],"levies":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","employee":1.0,"employer":1.0}],"rules":["text"],"source":"referral","publishedBy":"text","publishedAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/employees/{id}/salary-history","summary":"An employee's basic salary as dated figures, oldest first. Empty for a salary that has never been changed with a date.","auth":"jwt","responseKind":"json","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/salary-increases","summary":"A bulk increase: a percentage or an amount (exactly one) for the employees named, from a date. Repeating it on the same date lands on the same figure; a date inside an approved run is paid as back pay on the next run.","auth":"jwt","responseExample":{"changed":1,"lines":["text"]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll-periods/{id}/approval","summary":"Where the caller stands on approving the run: refused, naming who else may approve it, when they ran or last changed it; asked to confirm the sole approver's statement when nobody else can; otherwise free to approve. warning names, before approval, anyone on the run with PAYE withheld and no income tax reference number (their IRP5 needs one); it never refuses.","auth":"jwt","responseKind":"json","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll-periods/{id}/approve","summary":"Approve the run and lock the payslips. The person who ran or last changed it is refused while somebody else holds payroll approval; a sole approver adds ?confirmSoleApprover=true, and the statement is recorded.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/reopen?acknowledgeFiledEmp201=true","summary":"Reopen an approved period for correction. When the month's EMP201 is noted as filed it answers 409 EMP201_ALREADY_FILED until acknowledgeFiledEmp201=true.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-periods/{id}/pay","summary":"Record the payment run and post the journal.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","cashBankAccountId":"9b2e4d61-7a3c-4f85-b0d2-6e1f8a9c3b47"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodType":"2026-09","startDate":"2026-09-01","endDate":"2026-09-30","payDate":"2026-09-01","status":"sent","grossTotal":10005.0,"payeTotal":10005.0,"uifTotal":10005.0,"sdlTotal":10005.0,"nettTotal":8700.0,"employeeCount":3,"uifEmployeeTotal":10005.0,"uifEmployerTotal":10005.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"thirdPartyDeductionsTotal":10005.0,"employerRetirementTotal":10005.0,"employerMedicalTotal":10005.0,"employeeDeductionsTotal":10005.0,"employerContributionsTotal":10005.0,"costToCompanyTotal":10005.0,"deductionsReconcile":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll-periods/{id}/emp201","summary":"The EMP201 figures for a payroll period (payroll-licensed; the same figures the SARS returns centre shows).","auth":"jwt","responseExample":{"periodStart":"2026-09-01","periodEnd":"2026-09-30","totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"totalEtiCalculated":10005.0,"payeAfterEti":1.0,"totalPayable":13852.72,"employeeCount":3,"lines":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","paye":1.0,"uif":1.0,"sdl":1.0}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll-periods/{id}/payslips","summary":"Every payslip in a period.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","payDate":"2026-09-01","basicSalary":1.0,"travelAllowance":1.0,"overtime":1.0,"commission":1.0,"bonus":1.0,"otherAllowances":1.0,"grossSalary":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"employerRetirement":1.0,"employerMedical":1.0,"thirdPartyDeductions":1.0,"taxableRemuneration":1305.0,"travelInclusionRate":15.0,"payeTax":1305.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"netPay":8700.0,"ytdGross":1.0,"ytdPaye":1.0,"hoursWorked":3.0,"etiHoursSource":"referral","etiAmount":10005.0,"etiReason":"Budget deferred to the next financial year.","catchUpPaye":1.0,"catchUpNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","deductionLines":[{"beneficiaryName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","employeeAmount":10005.0,"employerAmount":10005.0}],"fringeBenefitsOtherRemuneration":1.0,"status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll-periods/{id}/journal","summary":"The journal the period posts, before or after posting.","auth":"jwt","responseExample":{"periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","payDate":"2026-09-01","periodStatus":"2026-09","state":"sent","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","lines":[{"accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0}],"totalDebit":10005.0,"totalCredit":10005.0,"balanced":true,"netPay":8700.0,"recordedNetPay":8700.0,"netPayVariance":8700.0,"employeeCount":3,"paymentLines":[{"accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0}],"paymentJournalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","paymentJournalNumber":"INV-0001","beneficiaries":[{"beneficiaryName":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","typeLabel":"Standard","employeeAmount":10005.0,"employerAmount":10005.0,"total":10005.0}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payslips/{id}","summary":"One payslip, line by line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","payDate":"2026-09-01","basicSalary":1.0,"travelAllowance":1.0,"overtime":1.0,"commission":1.0,"bonus":1.0,"otherAllowances":1.0,"grossSalary":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"employerRetirement":1.0,"employerMedical":1.0,"thirdPartyDeductions":1.0,"taxableRemuneration":1305.0,"travelInclusionRate":15.0,"payeTax":1305.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"netPay":8700.0,"ytdGross":1.0,"ytdPaye":1.0,"hoursWorked":3.0,"etiHoursSource":"referral","etiAmount":10005.0,"etiReason":"Budget deferred to the next financial year.","catchUpPaye":1.0,"catchUpNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","deductionLines":[{"beneficiaryName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","employeeAmount":10005.0,"employerAmount":10005.0}],"fringeBenefitsOtherRemuneration":1.0,"status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payslips/{id}","summary":"Adjust a payslip before the period is approved. earningUnits (per-unit types) and earningAmounts (fixed types) add or change a one-off named earning for this employee's period, whether or not the type is on their setup; a re-run keeps it. overtime is held as an amount on Ledgr's Overtime type; commission, bonus and otherAllowances are accepted for older clients and held as amounts on Ledgr's Commission, Bonus and Other allowances types, as earningAmounts would. Pension and medical aid come from the employee's deductions: a figure different from the payslip's is refused with 400.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","periodId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","periodEnd":"2026-09-30","payDate":"2026-09-01","basicSalary":1.0,"travelAllowance":1.0,"overtime":1.0,"commission":1.0,"bonus":1.0,"otherAllowances":1.0,"grossSalary":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"employerRetirement":1.0,"employerMedical":1.0,"thirdPartyDeductions":1.0,"taxableRemuneration":1305.0,"travelInclusionRate":15.0,"payeTax":1305.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"netPay":8700.0,"ytdGross":1.0,"ytdPaye":1.0,"hoursWorked":3.0,"etiHoursSource":"referral","etiAmount":10005.0,"etiReason":"Budget deferred to the next financial year.","catchUpPaye":1.0,"catchUpNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","deductionLines":[{"beneficiaryName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","employeeAmount":10005.0,"employerAmount":10005.0}],"fringeBenefitsOtherRemuneration":1.0,"status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"overtime":1.0,"commission":1.0,"bonus":1.0,"travelAllowance":1.0,"otherAllowances":1.0,"pensionContribution":1.0,"medicalAidContribution":1.0,"hoursWorked":3.0,"overtimeHours":3.0,"sundayHours":3.0,"publicHolidayHours":3.0,"hourlyRate":15.0,"overtimeRate":15.0,"earningUnits":{"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03":8.0},"earningAmounts":{"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03":150.0}},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payslips/{id}/pdf","summary":"The payslip as a PDF.","auth":"jwt","responseKind":"pdf","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payslips/{id}/send","summary":"Send a payslip by email or WhatsApp.","auth":"jwt","body":{"channel":"whatsapp"},"responseExample":{"payslipId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","channel":"email","delivered":true,"deliveryError":"text"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/irp5?taxYear=2027","summary":"The full IRP5 certificate set for a tax year, per employee, with the validation state e@syFile will apply. period=interim cuts the certificates at 31 August, as the interim EMP501 carries them; the default is annual. payPeriodsWorked is code 3210 as the certificate states it, a part period as its fraction (6.5 for a leaver of 15 September); monthsWorked is the same count rounded to a whole number and is kept only for compatibility.","auth":"jwt","responseExample":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","employeeNumber":"INV-0001","taxNumber":"9012345678","idNumber":"INV-0001","taxYear":"2027","certificateNumber":"INV-0001","certificateType":"standard","grossRemuneration":1.0,"payeDeducted":1.0,"uifTotal":10005.0,"sdl":1.0,"pensionTotal":10005.0,"medicalTotal":10005.0,"providentTotal":10005.0,"retirementAnnuityTotal":10005.0,"medicalTaxCredit":1305.0,"eti":1.0,"totalTaxSdlUif":1305.0,"employerRetirementBenefit":1.0,"employerMedicalBenefit":1.0,"monthsWorked":1,"payPeriodsWorked":1.0,"periodsInYear":12,"takeOnIncluded":false,"takeOnGrossRemuneration":1.0,"takeOnPaye":1.0,"takeOnSourceLabel":"Karoo Fresh Holdings Ltd"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/irp5/replace","summary":"Replace one employee's certificate: the standing certificate number is cancelled for good and the next is issued, which every later e@syFile file carries (BRS 3010). Ledgr tells SARS nothing — the cancellation is the employer's to make on e@syFile. 409 when the number given is no longer the standing one.","auth":"jwt","body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","certificateNumber":"712345678920270200000000E00001"},"responseExample":{"cancelled":"712345678920270200000000E00001","issued":"7123456789202702000000E00001R2"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/emp501?taxYear=2027","summary":"The EMP501 reconciliation figures for a tax year (payroll-licensed; the same figures the SARS returns centre shows).","auth":"jwt","responseExample":{"taxYear":"2027","months":[{"month":"2026-09","paye":1.0,"uif":1.0,"sdl":1.0,"eti":1.0,"total":10005.0,"paid":1.0}],"interimPaye":1.0,"interimUif":1.0,"interimSdl":1.0,"interimEti":1.0,"interimTotal":10005.0,"interimPaid":1.0,"annualPaye":1.0,"annualUif":1.0,"annualSdl":1.0,"annualEti":1.0,"annualTotal":10005.0,"annualPaid":1.0},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/easyfile","summary":"What the e@syFile export would contain, and any records that would fail it. Each certificate's payPeriodsWorked is code 3210 as the certificate states it, a part period as its fraction (7.5484 for a 15 July starter); periodsWorked is the same count rounded to a whole number and is kept only for compatibility.","auth":"jwt","responseExample":{"taxYear":"2027","periodFrom":"2026-09-01","periodTo":"2026-09-30","employerName":"Karoo Fresh Holdings Ltd","employerPayeNumber":"INV-0001","certificates":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","certificateNumber":"INV-0001","certificateType":"standard","employeeName":"Thandi Mokoena","taxNumber":"9012345678","idNumber":"INV-0001","periodsWorked":1,"payPeriodsWorked":1.0,"grossRemuneration":1.0,"paye":1.0,"uif":1.0,"sdl":1.0,"pension":1.0,"medical":1.0,"medicalTaxCredit":1305.0,"eti":1.0,"totalTaxSdlUif":1305.0,"validationErrors":["text"],"warnings":[],"valid":true,"takeOnIncluded":false,"takeOnGrossRemuneration":1.0,"takeOnPaye":1.0}],"totalGross":10005.0,"totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"totalEti":500.0,"excludedPaye":1.0,"excludedGross":1.0,"validCount":3,"invalidCount":3,"takeOnCount":3,"takeOnPaye":1.0,"takeOnGross":1.0,"blockingIssues":["The control account and the age analysis differ by R0.00."]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/easyfile/import-file?taxYear=2027&period=interim&test=false","summary":"The e@syFile Employer import file itself. period=interim|annual (default annual) chooses the reconciliation; test=true writes an e@syFile TEST import. 422 with the reasons when SARS's BRS would refuse the file.","auth":"jwt","responseKind":"csv","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/easyfile/emp501?taxYear=2027","summary":"The EMP501 schedule that goes with it.","auth":"jwt","responseKind":"csv","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/periods/{periodId}/remittances","summary":"Third-party remittances due for a period — medical aid, provident fund, garnishees.","auth":"jwt","responseExample":[{"beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","typeLabel":"Standard","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","remittanceEmail":"accounts@karoofresh.example","periodLabel":"2026-09","lines":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","memberReference":"INV-0001","employeeAmount":10005.0,"employerAmount":10005.0,"total":10005.0}],"employeeTotal":10005.0,"employerTotal":10005.0,"total":10005.0}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/beneficiaries","summary":"Third-party beneficiaries deductions are paid over to.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","typeLabel":"Standard","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","remittanceEmail":"accounts@karoofresh.example","notes":"Budget deferred to the next financial year.","isActive":true,"memberCount":3}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/beneficiaries","summary":"Add a beneficiary.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","typeLabel":"Standard","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","remittanceEmail":"accounts@karoofresh.example","notes":"Budget deferred to the next financial year.","isActive":true,"memberCount":3},"body":{"name":"Momentum Retirement Annuity","beneficiaryType":"retirement_fund","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","remittanceEmail":"contributions@momentum.example","notes":"Budget deferred to the next financial year.","isActive":true},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/beneficiaries/types","summary":"The beneficiary types and how each is treated for PAYE.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","reducesTax":false,"settles":false}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll/beneficiaries/{id}","summary":"Update a beneficiary.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","typeLabel":"Standard","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62012345678","bankBranchCode":"250655","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","remittanceEmail":"accounts@karoofresh.example","notes":"Budget deferred to the next financial year.","isActive":true,"memberCount":3},"body":{"name":"Momentum Retirement Annuity","beneficiaryType":"retirement_fund","accountReference":"INV-0001","bankName":"FNB","bankAccountNumber":"62099998888","bankBranchCode":"250655","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","remittanceEmail":"accounts@karoofresh.example","notes":"Budget deferred to the next financial year.","isActive":true},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/beneficiaries/{id}","summary":"Remove a beneficiary.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/deductions","summary":"Employee deductions and their remittance schedules.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","memberReference":"INV-0001","calculation":"fixed","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"totalOwing":10005.0,"totalPaid":10005.0,"outstanding":1.0,"orderReference":"INV-0001","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","s34AgreementDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","s34FaultConfirmed":false,"s34ProcedureDate":"2026-09-01","s34ActualLoss":1.0,"consentDate":"2026-02-20","consentReference":"Signed loan agreement, personnel file","packageNotice":"This run includes a catch-up deduction; the year-to-date total is correct."}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/deductions","summary":"Add a deduction against an employee.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","memberReference":"INV-0001","calculation":"fixed","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"totalOwing":10005.0,"totalPaid":10005.0,"outstanding":1.0,"orderReference":"INV-0001","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","s34AgreementDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","s34FaultConfirmed":false,"s34ProcedureDate":"2026-09-01","s34ActualLoss":1.0,"consentDate":"2026-02-20","consentReference":"Signed loan agreement, personnel file","packageNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memberReference":"INV-0001","calculation":"fixed","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"totalOwing":10005.0,"orderReference":"INV-0001","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","s34AgreementDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","s34FaultConfirmed":false,"s34ProcedureDate":"2026-09-01","s34ActualLoss":1.0,"consentDate":"2026-02-20","consentReference":"Signed loan agreement, personnel file","isFine":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/deductions/{id}","summary":"Change a deduction.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Karoo Fresh Holdings Ltd","beneficiaryType":"standard","memberReference":"INV-0001","calculation":"fixed","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"totalOwing":10005.0,"totalPaid":10005.0,"outstanding":1.0,"orderReference":"INV-0001","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","s34AgreementDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","s34FaultConfirmed":false,"s34ProcedureDate":"2026-09-01","s34ActualLoss":1.0,"consentDate":"2026-02-20","consentReference":"Signed loan agreement, personnel file","packageNotice":"This run includes a catch-up deduction; the year-to-date total is correct."},"body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memberReference":"INV-0001","calculation":"fixed","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"totalOwing":10005.0,"orderReference":"INV-0001","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","s34AgreementDocumentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","s34FaultConfirmed":false,"s34ProcedureDate":"2026-09-01","s34ActualLoss":1.0,"consentDate":"2026-02-20","consentReference":"Signed loan agreement, personnel file","isFine":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/deductions/{id}","summary":"End a deduction.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/cost-to-company","summary":"Structure a package backwards from a cost-to-company figure.","auth":"jwt","responseExample":{"costToCompany":10005.0,"basicSalary":1.0,"employerContributions":1.0,"employerUif":1.0,"employerSdl":1.0,"components":[{"label":"Karoo Fresh Holdings Ltd","amount":10005.0}]},"body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costToCompany":45000.0,"employerContributions":3200.0,"uifLiable":true,"sdlExempt":false,"apply":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/fringe-benefits","summary":"Fringe benefits in force.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","benefitType":"COMPANY_CAR","typeLabel":"Company car","description":"Consulting services — August 2026","determinedValue":10005.0,"maintenancePlanIncluded":false,"inputTaxClaimed":false,"employeeBearsMaintenance":false,"depreciationYears":1,"operatingLeaseCost":10005.0,"operatingLeaseFuelCost":10005.0,"businessUseAtLeast80":false,"employeeConsideration":1.0,"loanBalance":10005.0,"loanInterestPaid":1.0,"repoRate":15.0,"remunerationProxy":1.0,"abatementNil":false,"atLeastFourRooms":false,"furnished":false,"powerOrFuelSupplied":false,"employerExpenditure":1.0,"employeeRent":1.0,"monthlyAmount":10005.0,"noValueProvision":false,"noValueReason":"Budget deferred to the next financial year.","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","monthlyValue":10005.0,"monthlyRemuneration":1.0,"sourceCode":"CT-001","workings":"text","issue":"The control account and the age analysis differ by R0.00.","used":false}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/fringe-benefits","summary":"Add a fringe benefit. ","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","benefitType":"COMPANY_CAR","typeLabel":"Company car","description":"Consulting services — August 2026","determinedValue":10005.0,"maintenancePlanIncluded":false,"inputTaxClaimed":false,"employeeBearsMaintenance":false,"depreciationYears":1,"operatingLeaseCost":10005.0,"operatingLeaseFuelCost":10005.0,"businessUseAtLeast80":false,"employeeConsideration":1.0,"loanBalance":10005.0,"loanInterestPaid":1.0,"repoRate":15.0,"remunerationProxy":1.0,"abatementNil":false,"atLeastFourRooms":false,"furnished":false,"powerOrFuelSupplied":false,"employerExpenditure":1.0,"employeeRent":1.0,"monthlyAmount":10005.0,"noValueProvision":false,"noValueReason":"Budget deferred to the next financial year.","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","monthlyValue":10005.0,"monthlyRemuneration":1.0,"sourceCode":"CT-001","workings":"text","issue":"The control account and the age analysis differ by R0.00.","used":false},"body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","benefitType":"motor_vehicle","description":"Consulting services — August 2026","determinedValue":420000.0,"maintenancePlanIncluded":true,"inputTaxClaimed":false,"employeeBearsMaintenance":false,"depreciationYears":1,"operatingLeaseCost":10005.0,"operatingLeaseFuelCost":10005.0,"businessUseAtLeast80":false,"employeeConsideration":1.0,"loanBalance":10005.0,"loanInterestPaid":1.0,"repoRate":15.0,"remunerationProxy":1.0,"abatementNil":false,"atLeastFourRooms":false,"furnished":false,"powerOrFuelSupplied":false,"employerExpenditure":1.0,"employeeRent":1.0,"monthlyAmount":10005.0,"noValueProvision":false,"noValueReason":"Budget deferred to the next financial year.","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/fringe-benefits/types","summary":"The benefit types and the Seventh Schedule rule each follows.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","rule":"text","sourceCode":"CT-001"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll/fringe-benefits/{id}","summary":"Change a fringe benefit.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","benefitType":"COMPANY_CAR","typeLabel":"Company car","description":"Consulting services — August 2026","determinedValue":10005.0,"maintenancePlanIncluded":false,"inputTaxClaimed":false,"employeeBearsMaintenance":false,"depreciationYears":1,"operatingLeaseCost":10005.0,"operatingLeaseFuelCost":10005.0,"businessUseAtLeast80":false,"employeeConsideration":1.0,"loanBalance":10005.0,"loanInterestPaid":1.0,"repoRate":15.0,"remunerationProxy":1.0,"abatementNil":false,"atLeastFourRooms":false,"furnished":false,"powerOrFuelSupplied":false,"employerExpenditure":1.0,"employeeRent":1.0,"monthlyAmount":10005.0,"noValueProvision":false,"noValueReason":"Budget deferred to the next financial year.","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year.","monthlyValue":10005.0,"monthlyRemuneration":1.0,"sourceCode":"CT-001","workings":"text","issue":"The control account and the age analysis differ by R0.00.","used":false},"body":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","benefitType":"motor_vehicle","description":"Consulting services — August 2026","determinedValue":395000.0,"maintenancePlanIncluded":false,"inputTaxClaimed":false,"employeeBearsMaintenance":false,"depreciationYears":1,"operatingLeaseCost":10005.0,"operatingLeaseFuelCost":10005.0,"businessUseAtLeast80":false,"employeeConsideration":1.0,"loanBalance":10005.0,"loanInterestPaid":1.0,"repoRate":15.0,"remunerationProxy":1.0,"abatementNil":false,"atLeastFourRooms":false,"furnished":false,"powerOrFuelSupplied":false,"employerExpenditure":1.0,"employeeRent":1.0,"monthlyAmount":10005.0,"noValueProvision":false,"noValueReason":"Budget deferred to the next financial year.","startDate":"2026-09-01","endDate":"2026-09-30","isActive":true,"notes":"Budget deferred to the next financial year."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/fringe-benefits/{id}","summary":"End a fringe benefit.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/eti?month=2026-09","summary":"The Employment Tax Incentive as a view — who qualifies, which of the 24 months they are in, and what may be taken off PAYE.","auth":"jwt","responseExample":{"monthStart":"2026-09-01","monthEnd":"2026-09-30","monthLabel":"Karoo Fresh Holdings Ltd","bandTable":"text","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","dateOfBirth":"1988-04-12","startDate":"2026-09-01","ageAtMonthEnd":1,"qualifies":false,"qualifyingMonth":9,"monthsUsed":1,"firstYear":false,"amount":10005.0,"reason":"Budget deferred to the next financial year.","qualifiesButUnclaimed":false,"remuneration":1.0,"basis":"invoice","minimumWageMonthly":1.0,"noWageRegulatingMeasure":false,"monthsClaimedBeforeLedgr":1,"exclusion":"text","ordinaryHoursMonthly":3.0,"staleVsCapturedFacts":"text","hoursWorked":3.0,"hoursSource":"referral","sezCode":"COE"}],"qualifyingCount":3,"calculatedTotal":10005.0,"unclaimedCount":3,"recomputeCount":3,"claim":{"monthEnd":"2026-09-30","broughtForward":1.0,"calculated":1.0,"available":1.0,"utilised":1.0,"grossPaye":1.0,"netPaye":8700.0,"carriedForward":1.0,"ringFencedForRefund":1.0},"estimated":true,"employer":{"sezQualifyingCompany":false,"ineligibleEmployer":"pfma_public_entity","ineligibleReason":"This employer may not claim the Employment Tax Incentive: it is a public entity listed in Schedule 2 or 3 to the Public Finance Management Act (ETI Act s3(b)(ii))."}},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll/eti/employees/{id}?month=2026-09","summary":"Correct an employee's ETI eligibility or start month.","auth":"jwt","responseExample":{"monthStart":"2026-09-01","monthEnd":"2026-09-30","monthLabel":"Karoo Fresh Holdings Ltd","bandTable":"text","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","dateOfBirth":"1988-04-12","startDate":"2026-09-01","ageAtMonthEnd":1,"qualifies":false,"qualifyingMonth":9,"monthsUsed":1,"firstYear":false,"amount":10005.0,"reason":"Budget deferred to the next financial year.","qualifiesButUnclaimed":false,"remuneration":1.0,"basis":"invoice","minimumWageMonthly":1.0,"noWageRegulatingMeasure":false,"monthsClaimedBeforeLedgr":1,"exclusion":"text","ordinaryHoursMonthly":3.0,"staleVsCapturedFacts":"text","hoursWorked":3.0,"hoursSource":"referral","sezCode":"COE"}],"qualifyingCount":3,"calculatedTotal":10005.0,"unclaimedCount":3,"recomputeCount":3,"claim":{"monthEnd":"2026-09-30","broughtForward":1.0,"calculated":1.0,"available":1.0,"utilised":1.0,"grossPaye":1.0,"netPaye":8700.0,"carriedForward":1.0,"ringFencedForRefund":1.0},"estimated":true,"employer":{"sezQualifyingCompany":false,"ineligibleEmployer":"pfma_public_entity","ineligibleReason":"This employer may not claim the Employment Tax Incentive: it is a public entity listed in Schedule 2 or 3 to the Public Finance Management Act (ETI Act s3(b)(ii))."}},"body":{"dateOfBirth":"1988-04-12","startDate":"2026-09-01","etiMinimumWageMonthly":1.0,"clearMinimumWage":false,"etiNoWageRegulatingMeasure":true,"etiMonthsClaimedBeforeLedgr":6,"etiExclusion":"Connected person to the employer","etiOrdinaryHoursMonthly":3.0,"clearOrdinaryHours":false,"etiSezCode":"COE"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/eti/employer?month=2026-09","summary":"Record the employer's own ETI facts: whether it is a section 12R qualifying company in a special economic zone, and any ETI Act s3(b) ground that bars it from claiming.","auth":"jwt","responseExample":{"monthStart":"2026-09-01","monthEnd":"2026-09-30","monthLabel":"Karoo Fresh Holdings Ltd","bandTable":"text","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","dateOfBirth":"1988-04-12","startDate":"2026-09-01","ageAtMonthEnd":1,"qualifies":false,"qualifyingMonth":9,"monthsUsed":1,"firstYear":false,"amount":10005.0,"reason":"Budget deferred to the next financial year.","qualifiesButUnclaimed":false,"remuneration":1.0,"basis":"invoice","minimumWageMonthly":1.0,"noWageRegulatingMeasure":false,"monthsClaimedBeforeLedgr":1,"exclusion":"text","ordinaryHoursMonthly":3.0,"staleVsCapturedFacts":"text","hoursWorked":3.0,"hoursSource":"referral","sezCode":"COE"}],"qualifyingCount":3,"calculatedTotal":10005.0,"unclaimedCount":3,"recomputeCount":3,"claim":{"monthEnd":"2026-09-30","broughtForward":1.0,"calculated":1.0,"available":1.0,"utilised":1.0,"grossPaye":1.0,"netPaye":8700.0,"carriedForward":1.0,"ringFencedForRefund":1.0},"estimated":true,"employer":{"sezQualifyingCompany":false,"ineligibleEmployer":"pfma_public_entity","ineligibleReason":"This employer may not claim the Employment Tax Incentive: it is a public entity listed in Schedule 2 or 3 to the Public Finance Management Act (ETI Act s3(b)(ii))."}},"body":{"sezQualifyingCompany":true,"ineligibleEmployer":""},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/take-on","summary":"Opening year-to-date figures for an employer that switched to Ledgr part-way through a tax year.","auth":"jwt","responseExample":{"taxYearEndYear":2026,"taxYear":"2027","midYearSwitch":false,"firstLedgrPayDate":"2026-09-01","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","startDate":"2026-09-01","stated":false,"taxYearEndYear":2026,"taxYear":"2027","figures":{"taxYearEndYear":2026,"periodsWorked":1,"remuneration":1.0,"paye":1.0,"annualPayments":1.0,"payeOnAnnualPayments":1.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"retirementEmployee":1.0,"retirementEmployer":1.0,"medicalEmployee":1.0,"medicalEmployer":1.0,"medicalTaxCredit":1305.0,"fringeBenefits":1.0,"overtime":0.0,"commission":0.0,"travelAllowance":0.0,"otherAllowances":0.0,"fringeAccommodation":0.0,"fringeMedicalCosts":0.0},"provenance":{"source":"referral","sourceLabel":"Karoo Fresh Holdings Ltd","capturedAt":"2026-09-01T09:15:00Z","capturedBy":"text","note":"Budget deferred to the next financial year.","method":"eft"},"issues":[],"derivedPeriodsWorked":1,"periodsRunInLedgr":1}],"statedCount":3,"employeeCount":3,"totalRemuneration":10005.0,"totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"blockingCount":3,"warningCount":3},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/take-on/columns","summary":"The columns the take-on import expects.","auth":"jwt","responseExample":[{"header":"text","meaning":"text"}],"scope":"payroll:read"},{"method":"GET","path":"/api/payroll/take-on/template","summary":"A CSV template for the take-on.","auth":"jwt","responseKind":"csv","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/deductions/import/template","summary":"The blank recurring-deductions CSV, with a note per column and one worked example row.","auth":"jwt","responseKind":"csv","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/deductions/import/columns","summary":"Which columns Ledgr can match in a recurring-deductions file, so a caller can build one.","auth":"jwt","responseExample":[{"header":"text","meaning":"text"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/deductions/import","summary":"Preview or commit a recurring-deductions CSV. One code path, so the review cannot diverge from what the commit does.","auth":"jwt","body":{"csvContent":"Employee Number,Deduction,Amount\\nEMP001,Union dues,150.00","commit":false},"responseExample":{"committed":false,"applied":1,"skippedExisting":1,"beneficiariesCreated":1,"rows":[{"rowNumber":1,"employeeNumberGiven":"text","idNumberGiven":"text","taxNumberGiven":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","matchedOn":"2026-09-01","beneficiaryNameGiven":"text","beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryIsNew":false,"deductionTypeGiven":"text","calculationMethodGiven":"text","errors":[],"willImport":false,"alreadyExists":false}],"matchedCount":3,"unmatchedCount":3,"blockedCount":3,"readyCount":3,"detectedColumns":{"key":1},"unrecognisedHeaders":["text"],"errors":[],"canCommit":false,"message":"Saved."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/take-on/import","summary":"Import opening YTD figures.","auth":"jwt","responseExample":{"committed":false,"applied":1,"skipped":1,"taxYearEndYear":2026,"taxYear":"2027","rows":[{"rowNumber":1,"employeeNumberGiven":"text","idNumberGiven":"text","taxNumberGiven":"text","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","employeeNumber":"INV-0001","matchedOn":"2026-09-01","figures":{"taxYearEndYear":2026,"periodsWorked":1,"remuneration":1.0,"paye":1.0,"annualPayments":1.0,"payeOnAnnualPayments":1.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"retirementEmployee":1.0,"retirementEmployer":1.0,"medicalEmployee":1.0,"medicalEmployer":1.0,"medicalTaxCredit":1305.0,"fringeBenefits":1.0,"overtime":0.0,"commission":0.0,"travelAllowance":0.0,"otherAllowances":0.0,"fringeAccommodation":0.0,"fringeMedicalCosts":0.0},"issues":[],"willImport":false,"replacesExisting":false}],"matchedCount":3,"unmatchedCount":3,"blockedCount":3,"warningCount":3,"readyCount":3,"detectedColumns":{"key":1},"unrecognisedHeaders":["text"],"errors":[],"canCommit":false,"existingRunCount":3,"existingRunEmployeeCount":3,"requiresAcknowledgement":false,"acknowledgementMessage":"Saved.","message":"Saved."},"body":{"csvContent":"employeeCode,grossYtd,payeYtd\\nE001,240000,52000","taxYearEndYear":2027,"source":"OTHER","frequency":"MONTHLY","note":"Budget deferred to the next financial year.","commit":false,"acknowledgeExistingRuns":false},"scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/take-on/{employeeId}","summary":"Set one employee's opening figures by hand.","auth":"jwt","responseExample":{"taxYearEndYear":2026,"taxYear":"2027","midYearSwitch":false,"firstLedgrPayDate":"2026-09-01","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","startDate":"2026-09-01","stated":false,"taxYearEndYear":2026,"taxYear":"2027","figures":{"taxYearEndYear":2026,"periodsWorked":1,"remuneration":1.0,"paye":1.0,"annualPayments":1.0,"payeOnAnnualPayments":1.0,"uifEmployee":1.0,"uifEmployer":1.0,"sdl":1.0,"retirementEmployee":1.0,"retirementEmployer":1.0,"medicalEmployee":1.0,"medicalEmployer":1.0,"medicalTaxCredit":1305.0,"fringeBenefits":1.0,"overtime":0.0,"commission":0.0,"travelAllowance":0.0,"otherAllowances":0.0,"fringeAccommodation":0.0,"fringeMedicalCosts":0.0},"provenance":{"source":"referral","sourceLabel":"Karoo Fresh Holdings Ltd","capturedAt":"2026-09-01T09:15:00Z","capturedBy":"text","note":"Budget deferred to the next financial year.","method":"eft"},"issues":[],"derivedPeriodsWorked":1,"periodsRunInLedgr":1}],"statedCount":3,"employeeCount":3,"totalRemuneration":10005.0,"totalPaye":12400.0,"totalUif":1062.72,"totalSdl":890.0,"blockingCount":3,"warningCount":3},"body":{"taxYearEndYear":2026,"periodsWorked":1,"frequency":"MONTHLY","remuneration":240000.0,"paye":52000.0,"annualPayments":1.0,"payeOnAnnualPayments":1.0,"uifEmployee":1416.96,"uifEmployer":1.0,"sdl":1.0,"retirementEmployee":1.0,"retirementEmployer":1.0,"medicalEmployee":1.0,"medicalEmployer":1.0,"medicalTaxCredit":1305.0,"fringeBenefits":1.0,"overtime":0.0,"commission":0.0,"travelAllowance":0.0,"otherAllowances":0.0,"fringeAccommodation":0.0,"fringeMedicalCosts":0.0,"source":"OTHER","note":"Budget deferred to the next financial year.","acknowledgeExistingRuns":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/take-on/{employeeId}/eti-months?taxYearEndYear=2027","summary":"The Employment Tax Incentive an employee was claimed for in the months before the payroll moved onto Ledgr, month by month, as the certificate carries them.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","taxYearEndYear":2027,"months":[{"monthNumber":3,"cycle":1,"hours":160.0,"remuneration":4500.0,"minimumWage":2500.0,"wagePaid":4500.0,"etiAmount":1125.0}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll/take-on/{employeeId}/eti-months","summary":"Replace those months for the employee's take-on year (cycle 0 is a month considered and not claimed). Refuses a month Ledgr ran itself, a claim above the Act's monthly maximum, and a year the employee has no take-on figures for.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","taxYearEndYear":2027,"months":[{"monthNumber":3,"cycle":1,"hours":160.0,"remuneration":4500.0,"minimumWage":2500.0,"wagePaid":4500.0,"etiAmount":1125.0}]},"body":{"taxYearEndYear":2027,"months":[{"monthNumber":3,"cycle":1,"hours":160.0,"remuneration":4500.0,"minimumWage":2500.0,"wagePaid":4500.0,"etiAmount":1125.0}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/change-requests","summary":"Change requests employees have raised from the self-service portal.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","employeeNumber":"INV-0001","requestType":"standard","typeLabel":"Standard","isFinancial":true,"fields":[{"field":"text","label":"Karoo Fresh Holdings Ltd","current":"text","requested":"text","changed":true}],"employeeNote":"Budget deferred to the next financial year.","status":"sent","createdAt":"2026-09-01T09:15:00Z","reviewedAt":"2026-09-01T09:15:00Z","reviewedByName":"Karoo Fresh Holdings Ltd","reviewerNote":"Budget deferred to the next financial year."}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/change-requests/{id}/review","summary":"Approve or decline an employee's change request.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent"},"body":{"approve":true,"note":"Bank confirmation letter checked against the account number."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/employees/{id}/portal-link","summary":"Whether this employee has a self-service link, and when it was issued.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","active":true,"issuedAt":"2026-09-01T09:15:00Z","expiresAt":"2026-09-01T09:15:00Z","revokedAt":"2026-09-01T09:15:00Z","lastAccessedAt":"2026-09-01T09:15:00Z","accessCount":3},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/employees/{id}/portal-link","summary":"Issue a self-service link. Deliberately RELATIVE — /portal/employee/{token} — so the client composes the host it is already on, which is the better pattern where it applies.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","url":"https://app.ledgrsa.com/pay/3f1a7c92","expiresInDays":30,"replacedPreviousLink":false},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/employees/{id}/portal-link","summary":"Revoke the employee's link.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","active":true,"issuedAt":"2026-09-01T09:15:00Z","expiresAt":"2026-09-01T09:15:00Z","revokedAt":"2026-09-01T09:15:00Z","lastAccessedAt":"2026-09-01T09:15:00Z","accessCount":3},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/periods/{periodId}/cash-register","summary":"The cash pay register for an approved run: every employee paid in cash, what they are handed, and a column for their signature. Those employees are never on the salary payment file.","auth":"jwt","responseKind":"pdf","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/periods/{periodId}/payment-file?format=json&bank=fnb","summary":"The salary payment file for an approved run. format=json is the review — rows with the account number masked, the total, and every employee who cannot be paid with the reason. format=csv is the file itself and answers 422 with the reasons when anything blocks, because a file that silently omits the three employees whose banking details were never captured pays seven of ten people and still foots. bank=bankserv-acb is the Bankserv ACB file that Absa, Nedbank and Capitec import (180-character records, per the layout FNB publishes): it needs the ACB user code and the paying account's branch code saved in PUT /api/payroll-settings under banking, and answers 422 naming the setting when either is missing.","auth":"jwt","responseExample":{"payable":false,"payDate":"2026-09-01","totalAmount":10005.0,"paidCount":3,"notPaidCount":3,"rows":[{"employeeNumber":"INV-0001","beneficiaryName":"Karoo Fresh Holdings Ltd","bankName":"FNB","accountNumberMasked":"62012345678","branchCode":"250655","amount":10005.0,"reference":"INV-0001"}],"problems":[],"warnings":[]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/returns/uif-declaration?year=2026&month=3&submission=1&test=true","summary":"The month's UIF electronic declaration in the Department's own E03 format (U1, code and value), named as the Fund requires (the last eight digits of the UIF reference and the submission number), to e-mail to declarations@uif.gov.za. Every employee is declared, a non-contributor with the reason; the termination codes are E03's. Refused, naming what is missing, without a UIF reference that checks or a contact. test=true marks it TEST, validated by the Fund and not stored.","auth":"jwt","responseKind":"text","module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/returns/ui19?format=json","summary":"The UI-19 monthly declaration of employees to the UIF (uFiling). Carries the one thing the EMP201 does not — why each person stopped working here. A leaver with no reason captured, or one whose typed reason does not match a UI-19 reason, BLOCKS the return rather than being guessed at: a benefit claim is assessed against the declared reason, and the wrong one changes what the person may claim.","auth":"jwt","responseExample":{"filable":false,"year":2026,"month":9,"employeeCount":3,"leaverCount":3,"totalRemuneration":10005.0,"totalUifRemuneration":10005.0,"lines":[{"employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","identityKind":"standard","identityNumberMasked":"text","startDate":"2026-09-01","endDate":"2026-09-30","reasonCode":"CT-001","reasonLabel":"Karoo Fresh Holdings Ltd","remuneration":1.0,"uifRemuneration":1.0,"hoursPerMonth":3.0}],"issues":[]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/returns/roe?format=json","summary":"The COIDA Return of Earnings (W.As.8) for 1 March to end February. Earnings are capped PER EMPLOYEE, which is the whole arithmetic — capping the payroll total instead overstates the assessment for every employer with anybody above the ceiling. Ledgr does not invent the maximum: a year it has no compiled figure for is refused with instructions, or the employer supplies it as ?maxEarnings=.","auth":"jwt","responseExample":{"filable":false,"assessmentYearEnd":1,"periodLabel":"2026-09","maxEarnings":1.0,"employeeCount":3,"averageEmployees":1.0,"directorCount":3,"cappedEmployeeCount":3,"totalActualEarnings":10005.0,"totalAssessableEarnings":10005.0,"provisionalEstimate":1.0,"lines":[{"employeeNumber":"INV-0001","employeeName":"Thandi Mokoena","isDirector":false,"actualEarnings":1.0,"assessableEarnings":1.0,"cappedBy":1.0}],"issues":[]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll-settings","summary":"The tenant's payslip design and leave entitlements, plus the options the settings screen renders — the section list, the presets, and which sections the BCEA will not let you hide.","auth":"jwt","responseExample":{"design":{"title":"Karoo Fresh Holdings Ltd","accentHex":"#0D47A1","showLogo":true,"logoAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","logoScalePercent":100,"sections":[{"section":"EMPLOYER","visible":true}],"labels":{"key":"text"},"bankAccount":"masked","density":"compact","showTaxNumber":true,"showIdNumber":false,"message":"Saved.","footerText":"text","presetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"leave":{"annualDaysPerCycle":1.0,"annualAccrualPerMonth":1.0,"sickDaysPerCycle":1.0,"familyDaysPerCycle":1.0,"annualCarryOverDays":1.0},"logoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","logoInheritedFromInvoices":false,"presets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","forWhom":"text"}],"sections":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","required":true,"bceaReference":"INV-0001"}],"leaveCarryOverNote":"Budget deferred to the next financial year.","leaveIsStatutoryMinimum":true,"banking":{"payingBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","acbUserCode":"AB12","payingBranchCode":"632005"},"payingBankAccountOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","accountMasked":"text","bankName":"FNB"}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/payroll-settings","summary":"Update the payslip design, the leave entitlements, or both. A section-wise merge: a section the body does not name keeps its stored value. Refused with the BCEA subsection named if it would hide a required particular or set leave below the statutory minimum.","auth":"jwt","responseExample":{"design":{"title":"Karoo Fresh Holdings Ltd","accentHex":"#0D47A1","showLogo":true,"logoAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","logoScalePercent":100,"sections":[{"section":"EMPLOYER","visible":true}],"labels":{"key":"text"},"bankAccount":"masked","density":"compact","showTaxNumber":true,"showIdNumber":false,"message":"Saved.","footerText":"text","presetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"leave":{"annualDaysPerCycle":1.0,"annualAccrualPerMonth":1.0,"sickDaysPerCycle":1.0,"familyDaysPerCycle":1.0,"annualCarryOverDays":1.0},"logoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","logoInheritedFromInvoices":false,"presets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","forWhom":"text"}],"sections":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","required":true,"bceaReference":"INV-0001"}],"leaveCarryOverNote":"Budget deferred to the next financial year.","leaveIsStatutoryMinimum":true,"banking":{"payingBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","acbUserCode":"AB12","payingBranchCode":"632005"},"payingBankAccountOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","accountMasked":"text","bankName":"FNB"}]},"body":{"design":{"title":"Payslip","accentHex":"#0D47A1","showLogo":true,"logoAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","logoScalePercent":100,"sections":[{"section":"EMPLOYER","visible":true}],"labels":{"basic":"Basic salary"},"bankAccount":"masked","density":"compact","showTaxNumber":true,"showIdNumber":false,"message":"Saved.","footerText":"Queries: payroll@karoofresh.example","presetId":"monthly-salaried"},"leave":{"annualDaysPerCycle":21.0,"annualAccrualPerMonth":1.0,"sickDaysPerCycle":1.0,"familyDaysPerCycle":1.0,"annualCarryOverDays":5.0},"banking":{"payingBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","acbUserCode":"AB12","payingBranchCode":"632005"},"uif":{"departmentReference":"1916733/3","contactPerson":"Andy Owner","contactPhone":"0214441234","contactEmail":"payroll@acme.example"}},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-settings/preset/{presetId}","summary":"Apply a starting point — monthly-salaried, weekly-wage, cost-to-company, shift-and-overtime, small-employer or agriculture. Keeps the tenant's own title, accent, logo and message; replaces the section choices.","auth":"jwt","responseExample":{"design":{"title":"Karoo Fresh Holdings Ltd","accentHex":"#0D47A1","showLogo":true,"logoAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","logoScalePercent":100,"sections":[{"section":"EMPLOYER","visible":true}],"labels":{"key":"text"},"bankAccount":"masked","density":"compact","showTaxNumber":true,"showIdNumber":false,"message":"Saved.","footerText":"text","presetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"leave":{"annualDaysPerCycle":1.0,"annualAccrualPerMonth":1.0,"sickDaysPerCycle":1.0,"familyDaysPerCycle":1.0,"annualCarryOverDays":1.0},"logoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","logoInheritedFromInvoices":false,"presets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","forWhom":"text"}],"sections":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","required":true,"bceaReference":"INV-0001"}],"leaveCarryOverNote":"Budget deferred to the next financial year.","leaveIsStatutoryMinimum":true,"banking":{"payingBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","acbUserCode":"AB12","payingBranchCode":"632005"},"payingBankAccountOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","accountMasked":"text","bankName":"FNB"}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll-settings/logo","summary":"Upload the mark printed on the payslip. Raw PNG, JPEG or WebP bytes in the body; the attachment id is written into the settings itself, so there is nothing to save afterwards.","auth":"jwt","responseExample":{"design":{"title":"Karoo Fresh Holdings Ltd","accentHex":"#0D47A1","showLogo":true,"logoAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","logoScalePercent":100,"sections":[{"section":"EMPLOYER","visible":true}],"labels":{"key":"text"},"bankAccount":"masked","density":"compact","showTaxNumber":true,"showIdNumber":false,"message":"Saved.","footerText":"text","presetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"leave":{"annualDaysPerCycle":1.0,"annualAccrualPerMonth":1.0,"sickDaysPerCycle":1.0,"familyDaysPerCycle":1.0,"annualCarryOverDays":1.0},"logoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","logoInheritedFromInvoices":false,"presets":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","forWhom":"text"}],"sections":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","required":true,"bceaReference":"INV-0001"}],"leaveCarryOverNote":"Budget deferred to the next financial year.","leaveIsStatutoryMinimum":true,"banking":{"payingBankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","acbUserCode":"AB12","payingBranchCode":"632005"},"payingBankAccountOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","accountMasked":"text","bankName":"FNB"}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/employees/{id}/documents","summary":"One employee's document register with every expiry verdict, its own counts, and the kinds that may be filed.","auth":"jwt","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2026-09-01","expiryStatus":"NO_DATE","expirySentence":"text","daysUntilExpiry":30,"needsAttention":true,"source":"referral","verifiedAt":"2026-09-01T09:15:00Z","verifiedByName":"Karoo Fresh Holdings Ltd","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1,"createdAt":"2026-09-01T09:15:00Z"}],"kinds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","consequence":"text","expires":true,"employeeMayUpload":true}],"expiredCount":3,"expiringSoonCount":3,"attentionSummary":"Consulting services — August 2026","warnDays":30},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/employees/{id}/documents","summary":"File a document. Raw bytes in the body with kind, title, issuedOn and expiresOn as query parameters. A row with no file is accepted — recording that a PrDP expires in March, with the card still in the driver's wallet, is the register doing its most useful job.","auth":"jwt","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2026-09-01","expiryStatus":"NO_DATE","expirySentence":"text","daysUntilExpiry":30,"needsAttention":true,"source":"referral","verifiedAt":"2026-09-01T09:15:00Z","verifiedByName":"Karoo Fresh Holdings Ltd","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1,"createdAt":"2026-09-01T09:15:00Z"}],"kinds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","consequence":"text","expires":true,"employeeMayUpload":true}],"expiredCount":3,"expiringSoonCount":3,"attentionSummary":"Consulting services — August 2026","warnDays":30},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/employee-documents/{docId}","summary":"Correct the metadata. The file is never replaced — a renewed permit is a new row, so the register keeps what was valid when.","auth":"jwt","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2026-09-01","expiryStatus":"NO_DATE","expirySentence":"text","daysUntilExpiry":30,"needsAttention":true,"source":"referral","verifiedAt":"2026-09-01T09:15:00Z","verifiedByName":"Karoo Fresh Holdings Ltd","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1,"createdAt":"2026-09-01T09:15:00Z"}],"kinds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","consequence":"text","expires":true,"employeeMayUpload":true}],"expiredCount":3,"expiringSoonCount":3,"attentionSummary":"Consulting services — August 2026","warnDays":30},"body":{"kind":"invoice","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2027-03-31"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/employee-documents/{docId}/verify","summary":"Record that somebody with payroll:edit has looked at it. An employee-uploaded document is not verified by arriving.","auth":"jwt","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2026-09-01","expiryStatus":"NO_DATE","expirySentence":"text","daysUntilExpiry":30,"needsAttention":true,"source":"referral","verifiedAt":"2026-09-01T09:15:00Z","verifiedByName":"Karoo Fresh Holdings Ltd","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1,"createdAt":"2026-09-01T09:15:00Z"}],"kinds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","consequence":"text","expires":true,"employeeMayUpload":true}],"expiredCount":3,"expiringSoonCount":3,"attentionSummary":"Consulting services — August 2026","warnDays":30},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/employee-documents/{docId}","summary":"Soft delete. The stored file is left alone: a payroll screen is not where somebody should be able to shred the evidence behind an employment.","auth":"jwt","responseExample":{"status":"deleted"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/earning-types","summary":"What this business pays by name — a night-shift allowance, a rations allowance, a tool allowance — with the SARS code each reports under, and the codes and calculations a tenant may pick from.","auth":"jwt","responseExample":{"types":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"}],"codeOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","guidance":"text","taxable":true,"postsToLabel":"Karoo Fresh Holdings Ltd"}],"calculationOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd"}],"accountOptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd"}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/payroll/pay-templates","summary":"Pay templates — one per grade or role — with their effective-dated basic, earning and deduction lines and how many employees follow each. An employee's own figures override a template's.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","payBasis":"invoice","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":30,"ordinarilyWorksSundays":false,"shiftHours":3.0,"dayCapHours":3.0,"fundSalaryWeeklyHours":3.0,"fundSalaryWeeks":1.0,"agreements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","startsOn":"2026-09-01","endsOn":"2026-09-01","averageWeeklyHours":3.0,"overtimeWeeklyCap":1.0}],"rates":[{"effectiveFrom":"2026-09-01","monthlySalary":1.0,"hourlyRate":15.0}],"earnings":[{"earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","effectiveFrom":"2026-09-01","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0}],"deductions":[{"beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Highveld Provident Fund","effectiveFrom":"2026-09-01","base":"text","calculation":"text","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"unpaidLeave":"follows_base"}],"employeeCount":3}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/pay-templates","summary":"Create a pay template: its name, pay basis (monthly or hourly), working pattern and optional fund salary (weekly hours × weeks a month).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","payBasis":"invoice","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":30,"ordinarilyWorksSundays":false,"shiftHours":3.0,"dayCapHours":3.0,"fundSalaryWeeklyHours":3.0,"fundSalaryWeeks":1.0,"agreements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","startsOn":"2026-09-01","endsOn":"2026-09-01","averageWeeklyHours":3.0,"overtimeWeeklyCap":1.0}],"rates":[{"effectiveFrom":"2026-09-01","monthlySalary":1.0,"hourlyRate":15.0}],"earnings":[{"earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","effectiveFrom":"2026-09-01","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0}],"deductions":[{"beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Highveld Provident Fund","effectiveFrom":"2026-09-01","base":"text","calculation":"text","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"unpaidLeave":"follows_base"}],"employeeCount":3},"body":{"name":"Karoo Fresh Holdings Ltd","payBasis":"monthly","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":30,"ordinarilyWorksSundays":false,"shiftHours":3.0,"dayCapHours":3.0,"fundSalaryWeeklyHours":3.0,"fundSalaryWeeks":1.0,"council":"NBCPSS","councilGrade":"C","councilArea":"1"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/pay-templates/{id}","summary":"Rename a pay template or change its pay basis, working pattern or fund salary.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","payBasis":"invoice","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":30,"ordinarilyWorksSundays":false,"shiftHours":3.0,"dayCapHours":3.0,"fundSalaryWeeklyHours":3.0,"fundSalaryWeeks":1.0,"agreements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","startsOn":"2026-09-01","endsOn":"2026-09-01","averageWeeklyHours":3.0,"overtimeWeeklyCap":1.0}],"rates":[{"effectiveFrom":"2026-09-01","monthlySalary":1.0,"hourlyRate":15.0}],"earnings":[{"earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Overtime","effectiveFrom":"2026-09-01","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0}],"deductions":[{"beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","beneficiaryName":"Highveld Provident Fund","effectiveFrom":"2026-09-01","base":"text","calculation":"text","employeeAmount":10005.0,"employerAmount":10005.0,"employeePercent":15.0,"employerPercent":15.0,"unpaidLeave":"follows_base"}],"employeeCount":3},"body":{"name":"Karoo Fresh Holdings Ltd","payBasis":"monthly","ordinaryHoursWeekly":3.0,"ordinaryDaysWeekly":30,"ordinarilyWorksSundays":false,"shiftHours":3.0,"dayCapHours":3.0,"fundSalaryWeeklyHours":3.0,"fundSalaryWeeks":1.0,"council":"NBCPSS","councilGrade":"C","councilArea":"1"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/pay-templates/{id}/rates","summary":"The template's basic from a date — a monthly salary or a normal hourly rate. A new date is a new line (a yearly increase); the same date replaces it. Answers whom it reaches and who keeps their own.","auth":"jwt","body":{"effectiveFrom":"2026-03-01","monthlySalary":7003.0,"hourlyRate":null},"responseExample":{"employees":6,"overriddenBy":["Guard6 Scope"],"sentence":"This reaches 5 employees on the template; 1 employee keep their own figure (Guard6 Scope)."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/pay-templates/{id}/earnings","summary":"A named earning on the template from a date (an allowance, an hours category's rate). Answers whom it reaches and who has their own line for the type.","auth":"jwt","body":{"earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","effectiveFrom":"2026-03-01","amount":150.0,"percent":0.0,"rate":0.0,"units":0.0,"councilAllowance":"night"},"responseExample":{"employees":6,"overriddenBy":["Guard6 Scope"],"sentence":"This reaches 5 employees on the template; 1 employee keep their own figure (Guard6 Scope)."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/pay-templates/{id}/deductions","summary":"A deduction on the template from a date, its base named: basic, money (remuneration in money) or fund_salary; fixed or a percentage, with an employer share. A loan, savings, retirement annuity, union or other line names the collectiveAgreement it rests on (BCEA s34(1)(b)) or is refused. Answers whom it reaches and who has their own.","auth":"jwt","body":{"beneficiaryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","effectiveFrom":"2026-03-01","base":"fund_salary","calculation":"percent","employeeAmount":0.0,"employerAmount":0.0,"employeePercent":7.5,"employerPercent":7.5,"unpaidLeave":"employee_reduced","collectiveAgreement":null},"responseExample":{"employees":6,"overriddenBy":["Guard6 Scope"],"sentence":"This reaches 5 employees on the template; 1 employee keep their own figure (Guard6 Scope)."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/pay-templates/{id}/assign","summary":"Put one or many employees on a template. Their own figures still override it.","auth":"jwt","body":{"employeeIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"assigned":6},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/employees/{id}/tax-directives","summary":"An employee's tax directives: IRP3(b) a percentage, IRP3(c) an amount, a lump sum, or voluntary additional PAYE. While one is in force the payslip's PAYE follows it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","directiveNumber":"INV-0001","percent":15.0,"amount":10005.0,"validFrom":"2026-09-01","validTo":"2026-09-30","taxYearEnd":1}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/employees/{id}/tax-directives","summary":"Record a tax directive. Refused without its number, figure or start date, or when the tax year it names is not the one it starts in.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","directiveNumber":"INV-0001","percent":15.0,"amount":10005.0,"validFrom":"2026-09-01","validTo":"2026-09-30","taxYearEnd":1},"body":{"issuedOn":"2026-08-01","kind":"irp3b","directiveNumber":"0123456789","percent":18.0,"amount":null,"validFrom":"2026-03-01","validTo":"2027-02-28","taxYearEnd":2027},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/employees/{id}/tax-directives/{directiveId}","summary":"Remove a tax directive. PAYE comes from the tables from the next run.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/employees/{id}/averaging-agreements","summary":"One employee's own averaging agreements, which replace their template's.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","startsOn":"2026-09-01","endsOn":"2026-09-01","averageWeeklyHours":3.0,"overtimeWeeklyCap":1.0}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/averaging-agreements","summary":"Record an averaging agreement for a template or one employee — a collective agreement (BCEA s12) or a written one (NBCPSS clause 7(2)), at most four months.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","startsOn":"2026-09-01","endsOn":"2026-09-01","averageWeeklyHours":3.0,"overtimeWeeklyCap":1.0},"body":{"templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":null,"kind":"nbcpss_7_2","startsOn":"2026-10-01","endsOn":"2027-01-31","averageWeeklyHours":48.0,"overtimeWeeklyCap":12.0},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/averaging-agreements/{id}","summary":"Remove an averaging agreement. Hours are settled by the week from the next run.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payroll/earning-types","summary":"Set up a named earning. The SARS code decides the whole tax treatment: there is deliberately no taxable flag, because a second owner of that fact is how a payslip, an EMP201 and an IRP5 come to disagree about one rand.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"PUT","path":"/api/payroll/earning-types/{id}","summary":"Change a named earning. Payslips already raised keep what they paid — the name, code and amount are snapshotted onto the payslip.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/earning-types/{id}","summary":"Remove a named earning. Refused while any payslip carries it — switch it off instead, or the figure stays on those payslips and on the IRP5 with nothing in settings to explain it.","auth":"jwt","responseExample":{"status":"deleted"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/employees/{employeeId}/earnings","summary":"What this employee is on, what each comes to on their current basic pay, and which earnings they are not yet on.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","basicSalary":1.0,"earnings":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","unitLabel":"Karoo Fresh Holdings Ltd","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0,"usingDefault":true,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","taxable":true,"preview":1.0,"working":"text"}],"available":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"}]},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/payroll/employees/{employeeId}/earnings","summary":"Put an employee on a named earning, or correct the figure. An upsert: a second post is somebody fixing a number, not asking for a second line.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","basicSalary":1.0,"earnings":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","unitLabel":"Karoo Fresh Holdings Ltd","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0,"usingDefault":true,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","taxable":true,"preview":1.0,"working":"text"}],"available":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/payroll/employees/{employeeId}/earnings/{earningTypeId}","summary":"Take an employee off a named earning. Payslips already raised are untouched; the next run simply omits the line.","auth":"jwt","responseExample":{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","basicSalary":1.0,"earnings":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","unitLabel":"Karoo Fresh Holdings Ltd","amount":10005.0,"percent":15.0,"rate":15.0,"units":1.0,"usingDefault":true,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","taxable":true,"preview":1.0,"working":"text"}],"available":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","sarsCode":"CT-001","sarsLabel":"Karoo Fresh Holdings Ltd","calculation":"text","calculationLabel":"Karoo Fresh Holdings Ltd","defaultAmount":10005.0,"defaultPercent":15.0,"defaultRate":15.0,"unitLabel":"Karoo Fresh Holdings Ltd","active":true,"sortOrder":1,"notes":"Budget deferred to the next financial year.","taxable":true,"assignedCount":3,"glAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","postsToLabel":"Karoo Fresh Holdings Ltd","postsToIsDefault":true,"problem":"text"}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/payslips/bulk-send","summary":"Send every final payslip in one pay period, by email or WhatsApp. A draft is skipped and named rather than sent. Always 200 with a per-employee result, so one employee with no address does not fail the rest.","auth":"jwt","responseExample":{"channel":"email","sent":1,"failed":0,"skipped":1,"results":[{"payslipId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","channel":"email","delivered":true,"deliveryError":"text"}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/employees/irp5/bulk-send","summary":"Send a tax year's IRP5 certificates to the employees, by email (the certificate attached as a PDF) or WhatsApp (a notice that it is ready; refused on a plan that does not include WhatsApp). Only a certificate the employer may deliver is sent: a leaver's, or any employee's once the year has ended and its annual EMP501 is noted as filed. Every other employee is skipped and NAMED with the reason. Always 200 with a per-employee result, so one employee with no address does not fail the rest. taxYear is the year the tax year ends in; omitted, the current one.","auth":"jwt","body":{"taxYear":2026,"channel":"email"},"responseExample":{"taxYear":"2025/26","channel":"email","sent":1,"failed":0,"skipped":1,"results":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"E001","employeeName":"Thandi Mokoena","certificateNumber":"7012345676/2026/0001","channel":"email","delivered":true,"skipped":false},{"employeeId":"4a2b8d03-6c75-4e1f-8b22-3d8f9c5a7b14","employeeNumber":"E002","employeeName":"Sipho Dlamini","channel":"email","delivered":false,"skipped":true,"deliveryError":"Sipho Dlamini: The annual EMP501 for 2025/26 is not noted as filed, and a certificate is not delivered until it is."}]},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/payroll/document-expiries?window=30","summary":"Everything that has lapsed or lapses within 30 days, across every employee, expired first. Optional ?window= widens the horizon to at most a year.","auth":"jwt","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","issuedOn":"2026-09-01","expiresOn":"2026-09-01","expiryStatus":"NO_DATE","expirySentence":"text","daysUntilExpiry":30,"needsAttention":true,"source":"referral","verifiedAt":"2026-09-01T09:15:00Z","verifiedByName":"Karoo Fresh Holdings Ltd","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","contentType":"application/pdf","sizeBytes":1,"createdAt":"2026-09-01T09:15:00Z"}],"kinds":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","consequence":"text","expires":true,"employeeMayUpload":true}],"expiredCount":3,"expiringSoonCount":3,"attentionSummary":"Consulting services — August 2026","warnDays":30},"module":"payroll","plan":"Professional","scope":"payroll:read"}]},{"name":"Leave","blurb":"BCEA entitlements: 15 days annual, 30 days sick over a three-year cycle, three days family responsibility.","endpoints":[{"method":"GET","path":"/api/payroll/leave-liability?asOf=2026-06-30","summary":"What is owed for annual leave earned and not taken, and whether 2160 agrees. asOf (yyyy-mm-dd, today or earlier, default today) states both as at a reporting date: today's days less what later payroll runs granted plus leave dated after it that is already taken, beside 2160 to that day.","auth":"jwt","responseExample":{"asOf":"text","employees":[{"employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","costCentreName":"Karoo Fresh Holdings Ltd","unusedDays":1.0,"dailyRate":15.0,"provision":1.0,"basis":"invoice","employmentEnded":false}],"liability":1.0,"provisionAccountBalance":10005.0,"difference":1.0,"remeasuredAt":"2026-09-01T09:15:00Z","workingDaysPerYear":260},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"GET","path":"/api/leave-requests?status=pending&employeeId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Leave requests.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}],"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"POST","path":"/api/leave-requests","summary":"Raise a leave request.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","startDate":"2026-09-14","endDate":"2026-09-18","daysRequested":5.0,"reason":"Family holiday"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"GET","path":"/api/leave-requests/{id}","summary":"One request.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:read"},{"method":"PUT","path":"/api/leave-requests/{id}","summary":"Amend a pending request.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leaveType":"annual","startDate":"2026-09-14","endDate":"2026-09-17","daysRequested":4.0,"reason":"Budget deferred to the next financial year."},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"DELETE","path":"/api/leave-requests/{id}","summary":"Withdraw a request.","auth":"jwt","responseKind":"none","module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/leave-requests/{id}/approve","summary":"Approve leave and draw down the balance.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"},{"method":"POST","path":"/api/leave-requests/{id}/reject","summary":"Decline leave, with a reason.","auth":"jwt","body":{"reason":"Two people already off that week"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeName":"Thandi Mokoena","leaveType":"annual","startDate":"2026-09-01","endDate":"2026-09-30","daysRequested":1.0,"reason":"Budget deferred to the next financial year.","status":"sent","approvedBy":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"},"module":"payroll","plan":"Professional","scope":"payroll:write"}]},{"name":"Inventory","blurb":"Stock is valued at what the BATCHES cost — stockValue is the identity the ledger posts against, never costPrice × qty. On-hand cannot go below zero on any of the three write paths, and nothing that still holds stock can be deleted.","endpoints":[{"method":"GET","path":"/api/inventory/products?page=1&limit=50&search=laptop&category=Office%20supplies","summary":"The catalogue, paged. Search asks the SERVER, on name, SKU and barcode — the barcode arm matters because a typed barcode used to work only while the list was one page.","auth":"jwt","responseExample":{"items":[{"id":"d616ed4b-6b1d-5b94-88f6-9c115aed7e96","name":"Developer Kit","sku":"HW-DEV-K01","stockQty":42,"stockValue":336000.0}],"total":1340,"page":1,"limit":50,"totalPages":27},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/line-costs?productIds=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03,8d2e4b17-9c3a-4f60-b5d1-7e0a2c9f4b86","summary":"What each product costs on a quote, an order or a deal: a made product at its current standard, else its recipe's roll-up; a bought one at its cost price. Each answer names its basis. Only for roles that may see cost (mrp:view, bom:view or inventory:view). At most 200 products.","auth":"jwt","responseExample":{"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","unitCost":2900.0,"basis":"invoice"}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/products","summary":"Create a product. SKU is unique per tenant, case-insensitively, over live rows; a negative price and a VAT rate outside 0–100 are refused.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","units":{"key":1.0},"qtyPrecision":3,"barcode":"6001234567890","weightKg":1.0,"volumeM3":1.0,"unitsPerPallet":1.0,"costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"isSellable":false,"imageIcon":"text","thumbnailUrl":"https://app.ledgrsa.com/pay/3f1a7c92","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"vatType":"standard","shelfLifeDays":90,"gtin":"6001234567899","isReturnable":false,"returnableDeposit":0,"tempMinC":2,"tempMaxC":8,"preferredSupplierId":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"general","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"unit","qtyPrecision":3,"barcode":"6001234567890","weightKg":1.0,"volumeM3":1.0,"unitsPerPallet":1.0,"costingMethod":"FIFO","isTracked":true,"tracksSerials":false,"warrantyMonths":1,"isSellable":false,"imageIcon":"inventory","units":{"bag":25.0}},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/products/{id}","summary":"One product, with its stock value for the active company.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","qtyPrecision":3,"barcode":"6001234567890","costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"imageIcon":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/inventory/products/{id}","summary":"Update a product.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","units":{"key":1.0},"qtyPrecision":3,"barcode":"6001234567890","weightKg":1.0,"volumeM3":1.0,"unitsPerPallet":1.0,"costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"isSellable":false,"imageIcon":"text","thumbnailUrl":"https://app.ledgrsa.com/pay/3f1a7c92","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"vatType":"standard","shelfLifeDays":90,"gtin":"6001234567899","isReturnable":false,"returnableDeposit":0,"tempRange":{"minC":2,"maxC":8},"preferredSupplierId":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","qtyPrecision":3,"barcode":"6001234567890","weightKg":1.0,"volumeM3":1.0,"unitsPerPallet":1.0,"costingMethod":"eft","isTracked":true,"tracksSerials":true,"warrantyMonths":1,"isSellable":true,"imageIcon":"inventory","units":{"bag":25.0}},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/products/{id}","summary":"Soft-delete a product. REFUSED while there is stock to lose — a write-off has to be an adjustment somebody posts, not a silent disappearance with the value still sitting in 1310.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/products/lookup?sku=HW-DEV-K01&barcode=6001234567890","summary":"Resolve one product by barcode or SKU, for the scanner and the line picker. Takes the oldest match rather than nothing, for tenants whose data predates the uniqueness guard.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","qtyPrecision":3,"barcode":"6001234567890","costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"imageIcon":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/products/low-stock","summary":"Everything below its reorder point, tenant-wide — counting the loaded page would report page one's shortages as the whole catalogue.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","qtyPrecision":3,"barcode":"6001234567890","costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"imageIcon":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/products/summary","summary":"The catalogue's totals for the active company, over every live product rather than a page: how many products, how many are tracked or services, and the stock and sell value, composed row by row as the list composes them.","auth":"jwt","responseExample":{"totalProducts":156,"trackedProducts":151,"serviceProducts":5,"stockValue":10005.0,"sellValue":10005.0},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/products/low-stock-by-location","summary":"The same, split by location.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","qty":3.0,"reorderPoint":1.0,"reorderQty":3.0,"isLocationOverride":false}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/purchase-suggestions?locationId=4d8e2a61-7c3b-4f90-b5e2-8a1c6d9f3e27","summary":"What the low-stock list should buy, grouped by supplier: the reorder quantity where one is set, otherwise up to the reorder point, after what is already on order, rounded up to the product's counting precision. Without locationId, the active company's list; with it, that location's own thresholds. Products with no supplier (product, approved vendor list, then last purchase order) are listed apart; covered ones are named. Read-only — each draft is raised through POST /api/invoices with documentType \"po\".","auth":"jwt","responseExample":{"locationId":null,"locationName":null,"groups":[{"supplierId":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","supplierName":"Sasko Bakeries","lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"BRD-700","name":"Brown bread 700g","unit":"unit","qtyPrecision":0,"onHand":3.0,"onOrder":0.0,"reorderPoint":10.0,"reorderQty":null,"suggestedQty":7.0,"unitCost":12.0,"vatRate":15.0,"supplierId":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","supplierSource":"product"}]}],"unassigned":[{"productId":"9c2d7e41-0a5b-4f3c-8e6d-1b7a2c9f4e58","sku":"SLT-1","name":"Table salt 1kg","unit":"unit","qtyPrecision":0,"onHand":3.0,"onOrder":0.0,"reorderPoint":10.0,"reorderQty":null,"suggestedQty":5.0,"unitCost":12.0,"vatRate":15.0,"supplierId":null,"supplierSource":null}],"covered":[],"suppliers":[{"id":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","name":"Sasko Bakeries"}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/suppliers","summary":"Active suppliers, two fields each, for the product form's preferred-supplier picker — readable with inventory:view alone.","auth":"jwt","responseExample":[{"id":"7b1e4c2a-9d3f-4e8b-a6c1-5f2d8e9a0b14","name":"Sasko Bakeries"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/labels","summary":"A PDF sheet of product labels: name, SKU, shelf price and a barcode — EAN-13 when the product's barcode is a valid EAN-13, otherwise Code 128 of the barcode or the SKU. layout is a4-3x8 (24 to an A4 sheet) or roll-50x30 (one 50 x 30 mm label a page). Generated on each request, never stored.","auth":"jwt","responseKind":"pdf","body":{"items":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","copies":3}],"layout":"a4-3x8"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/products/{id}/images","summary":"Product photographs.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","base64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==","url":"https://app.ledgrsa.com/pay/3f1a7c92"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/products/{id}/images?clientId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Upload a photograph as a multipart file part, at most 5 MB; the server recompresses and stores the object, never base64 in Postgres. Send ?clientId= (the id the device minted for the photograph when it was staged): the first upload answers 201, a retry 200 with the photograph already stored, and an id already used by another business is refused. An unknown or deleted product answers 404.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","base64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==","url":"https://app.ledgrsa.com/pay/3f1a7c92"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/products/{id}/images/{imageId}","summary":"Remove a photograph.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/categories","summary":"Product categories.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","color":"#0D47A1","icon":"text","description":"Consulting services — August 2026","sortOrder":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/categories","summary":"Add a category.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","color":"#0D47A1","icon":"text","description":"Consulting services — August 2026","sortOrder":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"code":"CT-001","name":"Karoo Fresh Holdings Ltd","color":"#0D47A1","icon":"box","description":"Consulting services — August 2026","sortOrder":1,"accountCode":"6190"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/categories/{id}","summary":"Rename a category.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","color":"#0D47A1","icon":"text","description":"Consulting services — August 2026","sortOrder":1,"isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"code":"CT-001","name":"Workshop consumables","color":"#0D47A1","icon":"box","description":"Consulting services — August 2026","sortOrder":1,"isActive":true,"accountCode":"6190"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/categories/{id}","summary":"Remove a category.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/price-lists","summary":"Price lists visible in the active company, with how many prices and customers each carries. A price excludes VAT, like a product's sell price.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceCount":3,"customerCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/price-lists","summary":"Make a price list in the active company. Two live lists of the same name in one company are refused.","auth":"jwt","body":{"name":"Trade"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceCount":3,"customerCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/price-lists/{id}","summary":"Rename a price list.","auth":"jwt","body":{"name":"Trade customers"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceCount":3,"customerCount":3,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/price-lists/{id}","summary":"Delete a price list. Its customers go back to each product's own price, and the answer says how many did.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","customersDetached":1},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/price-lists/{id}/products?search=drill&page=1&limit=50","summary":"A list's price sheet: products (searched on name, SKU and barcode, paged) with their variants, each with its own sell price and the list's price.","auth":"jwt","responseExample":{"items":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","sellPrice":10005.0,"listPrice":10005.0,"variants":[{"variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","sellPrice":10005.0,"listPrice":10005.0}]}],"total":42,"page":1,"limit":50,"totalPages":1},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/inventory/price-lists/{id}/prices","summary":"Set one price on a list, for a product or one of its variants. No unitPrice clears it. Excludes VAT; stored at two decimals.","auth":"jwt","body":{"minQty":1.0,"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":null,"unitPrice":850.0},"responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","sellPrice":10005.0,"listPrice":10005.0,"variants":[{"variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","sellPrice":10005.0,"listPrice":10005.0}]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/variants?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Product variants — size, colour, configuration — each with its on-hand counted from the batches tagged to it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","attributes":"text","costPrice":10005.0,"sellPrice":10005.0,"stockQty":3.0,"barcode":"6001234567890","isActive":true,"createdAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/variants","summary":"Add a variant, optionally with opening stock opened as a batch (a typed stock figure is refused).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","attributes":"text","costPrice":10005.0,"sellPrice":10005.0,"stockQty":3.0,"barcode":"6001234567890","isActive":true,"createdAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"HW-DEV-K01-16-512","name":"16GB / 512GB","attributes":"{\"colour\":\"black\"}","costPrice":10005.0,"sellPrice":14500.0,"stockQty":null,"openingQty":3.0,"openingUnitCost":10005.0,"barcode":"6001234567890"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/variants/{id}","summary":"Update a variant.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","attributes":"text","costPrice":10005.0,"sellPrice":10005.0,"stockQty":3.0,"barcode":"6001234567890","isActive":true,"createdAt":"2026-09-01T09:15:00Z"},"body":{"sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","attributes":"{\"colour\":\"black\"}","costPrice":10005.0,"sellPrice":14900.0,"stockQty":null,"barcode":"6001234567890","isActive":true},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/variants/{id}","summary":"Remove a variant.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/reports/valuation?asOf=2026-09-01","summary":"Stock value as at a date, per product, beside the Inventory account (1310) on that date and the difference. Today is read from the open batches; an earlier date is rebuilt from the stock movements and says so.","auth":"jwt","responseExample":{"asOf":"2026-09-01","basis":"movements","exact":false,"note":"Rebuilt from today's batches by reversing 12 stock movements dated after 2026-09-01, each at the cost it moved at.","rows":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Lenovo ThinkPad 14","unit":"each","qty":3.0,"value":30015.0,"locations":[]}],"locations":[],"totalValue":30015.0,"ledgerBalance":30015.0,"difference":0.0,"movementsReversed":12,"movementsWithoutCost":0},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/reports/aging","summary":"Open batch quantity and value by age — 0–30, 31–90, 91–180 and over 180 days from each batch's received date — per product, totalling the stock value.","auth":"jwt","responseExample":{"asOf":"2026-09-01","bands":[{"key":"0-30","label":"0–30 days","value":30015.0},{"key":"31-90","label":"31–90 days","value":0.0},{"key":"91-180","label":"91–180 days","value":0.0},{"key":"180+","label":"Over 180 days","value":0.0}],"rows":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Lenovo ThinkPad 14","unit":"each","qty":[3.0,0.0,0.0,0.0],"value":[30015.0,0.0,0.0,0.0],"totalQty":3.0,"totalValue":30015.0}],"totalValue":30015.0},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/locations","summary":"Stock locations.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","address":"12 Long Street, Cape Town, 8001","type":"standard","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/locations","summary":"Add a location.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","address":"12 Long Street, Cape Town, 8001","type":"standard","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Durban Showroom","address":"12 Long Street, Cape Town, 8001","type":"standard","suburb":"Umhlanga","city":"Durban"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/locations/{id}","summary":"Rename a location.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","address":"12 Long Street, Cape Town, 8001","type":"standard","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"Durban Showroom (Umhlanga)","address":"12 Long Street, Cape Town, 8001","type":"standard","isActive":true,"suburb":"Umhlanga","city":"Durban"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/locations/{id}","summary":"Remove a location. REFUSED while it holds stock — its stock_levels rows would otherwise point at a warehouse no list shows, while still counting towards the product's total.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/locations/{id}/sell-from","summary":"Make this the location the company's sales ship from (\"Sell from here\"). Invoices, credit notes, reservations, deliveries and job-card parts take and return stock here. Until a company chooses, sales ship from the first location holding stock. Answers the company's locations, with sellsFrom on the one sales now use.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Durban Showroom","address":"12 Long Street, Cape Town, 8001","type":"standard","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","sellFromChosen":true,"sellsFrom":true}],"body":{},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/stock-levels?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"On-hand by product and location.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/products/{id}/pool-stock","summary":"A product's stock at the other companies this one shares inventory with.","auth":"jwt","responseExample":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyName":"Highveld Trading Co (Pty) Ltd","locationName":"Main warehouse","qty":3.0}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/movements?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Stock movement history with a running balance.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","type":"standard","qty":3.0,"reference":"INV-0001","balance":10005.0,"createdAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/adjust","summary":"Adjust stock up or down and post the journal. A negative resulting level is refused.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","category":"Office supplies","costPrice":10005.0,"sellPrice":10005.0,"vatRate":15.0,"stockQty":3.0,"reorderPoint":1.0,"unit":"each","qtyPrecision":3,"barcode":"6001234567890","costingMethod":"eft","isTracked":true,"stockValue":10005.0,"tracksSerials":false,"warrantyMonths":1,"imageIcon":"text","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","deltaQty":2.0,"reason":"Captured during the August review","reasonCode":"count","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/write-down-to-nrv","summary":"Carry a product's stock at the lower of cost and net realisable value: lowers the open batches to the NRV and posts the write-down, or raises batches written down earlier, never above cost.","auth":"jwt","responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","nrvPerUnit":8700.0,"writtenDown":74400.0,"reversed":0.0,"layers":1,"stockValue":208800.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","nrvPerUnit":8700.0,"reason":"Plate price fell; NRV quoted by two mills","date":"2026-02-28"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/reorder-points?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Reorder points and reorder quantities.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reorderPoint":1.0,"reorderQty":3.0}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/inventory/reorder-points","summary":"Set a reorder point.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reorderPoint":1.0,"reorderQty":3.0},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reorderPoint":20.0,"reorderQty":100.0},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/transfers","summary":"Inter-location transfers.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"reference":"INV-0001","status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/transfer","summary":"Raise a transfer. A shortfall is refused rather than driving the source negative, and the batch layers travel with the goods.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"reference":"INV-0001","status":"sent","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":2.0,"reference":"INV-0001"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/transfers/{id}/confirm","summary":"Receive a transfer. StockCostingEngine.relocate moves the batch layers HERE — on receipt, not on despatch, because the sum of batch values has to keep equalling 1310 at every instant.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"received","qty":3.0,"tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"TRF-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T11:40:00Z"},"body":{"notes":"Received in full, no damage"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/transfers/{id}/cancel","summary":"Cancel a transfer in flight.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"cancelled","qty":3.0,"tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"TRF-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T11:40:00Z"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/grni?asOf=2026-10-31","summary":"Goods received by hand and not yet invoiced, oldest first — the aged list behind 2115 Goods Received Not Invoiced for receipts with no order. A bill line, expense or bank line that names the product clears a receipt.","auth":"jwt","responseExample":{"asOf":"2026-10-31","receipts":[{"receiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Steel bar","supplier":"Karoo Fresh Holdings Ltd","receivedOn":"2026-10-12","daysOpen":19,"qtyOpen":10.0,"unitCost":100.0,"value":1000.0}],"total":1000.0},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/batches?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Batch layers — quantity remaining, unit cost, supplier, received and expiry dates, and the location they are actually at.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","expiryDate":"2026-09-01","qtyReceived":1.0,"qtyRemaining":1.0,"unitCost":2900.0,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/batches","summary":"Create a batch layer — receive stock by hand. kind says what the units are: purchase (the default; owed to the supplier until a bill, expense or bank line names the product — DR 1310 / CR 2115), found (stock found on a count — CR 5070) or opening (stock already owned when the books opened — CR 3500).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","expiryDate":"2026-09-01","qtyReceived":1.0,"qtyRemaining":1.0,"unitCost":2900.0,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-30","expiryDate":"2027-08-20","qtyReceived":2.0,"unitCost":1500.0,"notes":"Budget deferred to the next financial year.","serialNumbers":["INV-0001"],"kind":"purchase"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/batches/expiring?days=30","summary":"Batches expiring inside a window, with the location that holds them — naming the wrong branch is worse than naming none.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","batchNumber":"INV-0001","expiryDate":"2026-09-01","daysUntilExpiry":30,"qtyRemaining":1.0,"locationName":"Karoo Fresh Holdings Ltd"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"DELETE","path":"/api/inventory/batches/{id}","summary":"Remove an empty batch layer.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/batches/{id}/recall","summary":"Recall a lot: every customer it went to, with the document and quantity, and what is still on hand. On the Inventory licence.","auth":"jwt","responseExample":{"direction":"forward","rootBatchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootBatchNumber":"INV-0001","rootProductName":"Karoo Fresh Holdings Ltd","rootSku":"LEN-TP-14G4","nodes":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"unitCost":2900.0,"supplier":"Karoo Fresh Holdings Ltd","expiryDate":"2026-09-01","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","workOrderStatus":"sent","consumedAt":"2026-09-01T09:15:00Z","depth":1,"kind":"standard"}],"maxDepth":1,"truncated":false,"unaccountedQty":3.0,"receivers":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","date":"2026-09-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143"}],"receivedQty":3.0,"onHandQty":3.0,"quarantined":false},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/batches/{id}/quarantine","summary":"Quarantine what is left of a lot: it stays valued but nothing may sell, issue or build from it. Answers the recall.","auth":"jwt","responseExample":{"direction":"forward","rootBatchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootBatchNumber":"INV-0001","rootProductName":"Karoo Fresh Holdings Ltd","rootSku":"LEN-TP-14G4","nodes":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"unitCost":2900.0,"supplier":"Karoo Fresh Holdings Ltd","expiryDate":"2026-09-01","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","workOrderStatus":"sent","consumedAt":"2026-09-01T09:15:00Z","depth":1,"kind":"standard"}],"maxDepth":1,"truncated":false,"unaccountedQty":3.0,"receivers":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","date":"2026-09-01","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143"}],"receivedQty":3.0,"onHandQty":3.0,"quarantined":false},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/serials?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&invoiceId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&status=in_stock&q=cape","summary":"Serialised units and their status.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/serials","summary":"Register serial numbers against a batch.","auth":"jwt","responseExample":{"created":1,"duplicates":["text"],"serials":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"}]},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serials":["SN-0001","SN-0002"],"rangePrefix":"INV-","rangeStart":1,"rangeCount":3,"rangePad":1,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"notes":"Budget deferred to the next financial year."},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/serials/{id}","summary":"One serialised unit and its history.","auth":"jwt","responseExample":{"serial":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"},"events":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","event":"text","fromStatus":"sent","toStatus":"sent","occurredAt":"2026-09-01T09:15:00Z","reference":"INV-0001","notes":"Budget deferred to the next financial year."}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/serials/lookup?serial=SN-0001","summary":"Find a unit by its serial.","auth":"jwt","responseExample":{"serial":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"},"events":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","event":"text","fromStatus":"sent","toStatus":"sent","occurredAt":"2026-09-01T09:15:00Z","reference":"INV-0001","notes":"Budget deferred to the next financial year."}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/serials/summary","summary":"Counts by status — in stock, sold, returned, scrapped.","auth":"jwt","responseExample":{"totalSerials":1,"inStock":1,"sold":1,"returned":1,"scrapped":1,"underWarranty":1,"warrantyExpiringSoon":1,"unconfirmedAssignments":1,"products":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","stockQty":3.0,"serialsOnHand":1,"serialsSold":1,"uncaptured":1,"orphanedSerials":1}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/serials/assign","summary":"Assign serials to a document line at despatch.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"}],"body":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/serials/{id}/scrap","summary":"Write a unit off. Drains its OWN batch by one at that batch's cost — specific identification, which is the point of a serial — and posts DR 5070 / CR 1310. Only from in_stock.","auth":"jwt","body":{"notes":"Water damage"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/serials/{id}/return","summary":"Return a unit to stock. A returned unit is back on the shelf only if a credit note restocked it.","auth":"jwt","body":{"notes":"Customer return, resold as open-box"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialNumber":"INV-0001","batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplier":"Karoo Fresh Holdings Ltd","receivedDate":"2026-09-01","unitCost":2900.0,"status":"sent","soldDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","autoAssigned":false,"warrantyExpiry":"2026-09-30","warrantyDaysRemaining":30,"underWarranty":false,"notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/serials/{id}","summary":"Remove a serial registered in error.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/adjustment-reasons","summary":"The business's adjustment reasons — the defaults and its own — and whether an adjustment must give one.","auth":"jwt","responseExample":{"reasons":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","builtIn":true}],"requireReason":false},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/adjustment-reasons","summary":"Add one of the business's own adjustment reasons.","auth":"jwt","body":{"label":"Warranty return"},"responseExample":{"reasons":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","builtIn":true}],"requireReason":false},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/reports/adjustments-by-reason?dateFrom=2026-10-01&dateTo=2026-10-31","summary":"Adjustments by reason over a date range (dateFrom, dateTo): what each reason added and took away; the rows add up to every adjustment.","auth":"jwt","responseExample":{"dateFrom":"2026-09-01","dateTo":"2026-09-30","rows":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","adjustments":1,"qtyIn":1.0,"qtyOut":1.0,"value":10005.0}],"adjustments":1,"value":10005.0},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/bins?locationId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The bins inside the company's locations, with how many products each keeps.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","products":1}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/bins","summary":"Add a bin to a location.","auth":"jwt","body":{"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"A-01","name":"Power tools"},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","products":1}],"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PUT","path":"/api/inventory/products/{id}/bin","summary":"Keep a product in a bin at a location, or clear it.","auth":"jwt","responseKind":"none","body":{"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","binId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/cycle-counts","summary":"Cycle-count schedules, each raising one stock take a period.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","cadence":"text","scope":"text","abcClass":"text","binId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","binCode":"CT-001","active":true,"lastPeriod":"2026-09"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/cycle-counts","summary":"Schedule a cycle count — weekly, monthly or quarterly; all of a location, one ABC class or one bin. This period's count is raised at once.","auth":"jwt","body":{"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","cadence":"monthly","scope":"abc","abcClass":"A","binId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","active":true},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","cadence":"text","scope":"text","abcClass":"text","binId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","binCode":"CT-001","active":true,"lastPeriod":"2026-09"}],"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/cycle-counts/{id}","summary":"Stop a cycle-count schedule; counts already raised stay.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/pick-list?locationId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The pick list: what every open delivery note and open sales order asks the stock room to fetch, by location and bin, with on-hand beside it.","auth":"jwt","responseExample":{"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","binCode":"CT-001","quantity":3.0,"onHand":1.0,"sources":[{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","documentType":"invoice","contactName":"Karoo Fresh Holdings Ltd","lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0}]}],"notes":1,"orders":1},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/backorders","summary":"Open sales orders still owing something after a pick, line by line.","auth":"jwt","responseExample":[{"orderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","contactName":"Karoo Fresh Holdings Ltd","backordered":1.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","ordered":1.0,"backordered":1.0}]}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/pick-list/orders/{id}/pick","summary":"Pick a sales order: a delivery note is raised for what was picked, and what was not stays owed as a backorder. Replay-safe on clientId.","auth":"jwt","body":{"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","picked":3.0}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"noteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","noteNumber":"INV-0001","backorder":{"orderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","contactName":"Karoo Fresh Holdings Ltd","backordered":1.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","ordered":1.0,"backordered":1.0}]}},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/stock-takes","summary":"Stock takes and their variance.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/stock-takes","summary":"Open a stock take.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]},"body":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","category":"Office supplies"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/stock-takes/{id}","summary":"One stock take with its counted lines.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/inventory/stock-takes/{id}/lines","summary":"Save counts. The variance is written WHEN COUNTS ARE SAVED, not only at commit — the list used to tell a supervisor a count with eight units missing was clean.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]},"body":{"counts":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","countedQty":2.0}]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/stock-takes/{id}/commit","summary":"Post the variance as adjustments.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/inventory/stock-takes/{id}/cancel","summary":"Abandon a stock take.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","status":"sent","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","lineCount":3,"totalVariance":10005.0,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","expectedQty":3.0,"countedQty":3.0,"variance":1.0}]},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/boms?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Assembly recipes. These are V96's simple recipes at the Business tier; the deep BOM work is /api/bom on the Manufacturing plan.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","createdAt":"2026-09-01T09:15:00Z","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/boms","summary":"Create a recipe.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","createdAt":"2026-09-01T09:15:00Z","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","kind":"co","qtyPerRun":1.0,"unitValue":10005.0,"sharePercent":15.0,"sortOrder":1,"notes":"Budget deferred to the next financial year."}],"kind":"standard","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"active","notes":"Budget deferred to the next financial year.","effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1,"sourceOverride":"make","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","operationSeq":1}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/boms/{id}","summary":"One recipe.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","createdAt":"2026-09-01T09:15:00Z","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"PUT","path":"/api/inventory/boms/{id}","summary":"Change a recipe.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","createdAt":"2026-09-01T09:15:00Z","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","kind":"co","qtyPerRun":1.0,"unitValue":10005.0,"sharePercent":15.0,"sortOrder":1,"notes":"Budget deferred to the next financial year."}],"kind":"standard","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"active","notes":"Budget deferred to the next financial year.","effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1,"sourceOverride":"make","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","operationSeq":1}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/inventory/boms/{id}","summary":"Delete a recipe.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/boms/{id}/cost?qty=1","summary":"What the recipe costs at current batch costs.","auth":"jwt","responseExample":{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runsNeeded":1,"qtyToBuild":1.0,"components":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"qtyRequired":1.0,"available":1,"shortfall":1.0,"unitCost":2900.0,"lineCost":10005.0,"isTracked":true,"hasOwnBom":false}],"componentCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"maxBuildable":1.0,"blockers":[],"canBuild":true},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/boms/using/{productId}","summary":"Which recipes use this component.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","createdAt":"2026-09-01T09:15:00Z","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/disassemblies?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Products broken back into their parts. Newest first, bounded.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"parentValue":10005.0,"partsValue":10005.0,"residue":1.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","brokenAt":"2026-09-01T09:15:00Z","parts":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qtyRecovered":1.0,"unitCost":2900.0,"value":10005.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/disassemblies","summary":"Break a product back into its parts using its recipe — a case of 24 into singles, a returned unit into spares. The parts inherit exactly what the parent's own batches cost, split by their share of the recipe's material value; scrap is NOT recovered, because it was consumed making the thing. Both legs are 1310, so the only ledger entry is the rounding a four-place unit cost cannot hold, written off to 5070 so the batch total and 1310 stay tied exactly.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"parentValue":10005.0,"partsValue":10005.0,"residue":1.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","brokenAt":"2026-09-01T09:15:00Z","parts":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qtyRecovered":1.0,"unitCost":2900.0,"value":10005.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"body":{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":2.0,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","notes":"Budget deferred to the next financial year."},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/disassemblies/{id}","summary":"One disassembly, with the parts it recovered and what each was given.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"parentValue":10005.0,"partsValue":10005.0,"residue":1.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","brokenAt":"2026-09-01T09:15:00Z","parts":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qtyRecovered":1.0,"unitCost":2900.0,"value":10005.0,"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"GET","path":"/api/inventory/builds?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Assembly builds.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyBuilt":1.0,"status":"sent","componentCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","builtAt":"2026-09-01T09:15:00Z","lines":[{"componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","qtyRequired":1.0,"qtyConsumed":1.0,"unitCost":2900.0,"totalCost":10005.0,"short":false}]}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/builds","summary":"Build assemblies from components. A short build is REFUSED, naming what is short and what maxBuildable says can be built now — costing a shortfall at list price once put the sum of batch values R61 441 above 1310 with no entry that could close it.","auth":"jwt","responseExample":{"build":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyBuilt":1.0,"status":"sent","componentCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","builtAt":"2026-09-01T09:15:00Z","lines":[{"componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","qtyRequired":1.0,"qtyConsumed":1.0,"unitCost":2900.0,"totalCost":10005.0,"short":false}]},"shortComponents":["text"]},"body":{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyToBuild":2.0,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","notes":"Budget deferred to the next financial year."},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"GET","path":"/api/inventory/builds/{id}","summary":"One build and what it consumed.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyBuilt":1.0,"status":"sent","componentCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","builtAt":"2026-09-01T09:15:00Z","lines":[{"componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","qtyRequired":1.0,"qtyConsumed":1.0,"unitCost":2900.0,"totalCost":10005.0,"short":false}]},"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/inventory/builds/{id}/cancel","summary":"Reverse a build, returning components to their layers.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyBuilt":1.0,"status":"sent","componentCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"reference":"INV-0001","notes":"Budget deferred to the next financial year.","builtAt":"2026-09-01T09:15:00Z","lines":[{"componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","qtyRequired":1.0,"qtyConsumed":1.0,"unitCost":2900.0,"totalCost":10005.0,"short":false}]},"module":"inventory","plan":"Business","scope":"inventory:write"}]},{"name":"Job cards","blurb":"The field-service and workshop job. A job's cost is what the business SPENT — allocating a purchase writes ONE job_card_costs row carrying source_expense_id or source_bill_id, so double counting is impossible.","endpoints":[{"method":"GET","path":"/api/job-cards?status=in_progress&page=1&limit=50&contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&technicianId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&search=cape&scheduled=true&priority=normal","summary":"Job cards, server-paged and server-filtered. It used to fetch one page of 100 and filter client-side, so a workshop lost its history after a fortnight.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]}],"total":42,"page":1,"limit":20,"totalPages":1},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards","summary":"Raise a job. Accepts a client-minted id, which is what makes offline capture replayable — the CARD queues, but issuing parts and converting stay online-only.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","workRequested":"Replace element and thermostat","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","technicianUserIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serialId":"5c2d8e14-6f3a-4b97-a0d1-7e9f2c4b6a18","serialNumber":"CB-24-0007","serviceContractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/{id}","summary":"One job with its labour, parts, costs and sign-off.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"PUT","path":"/api/job-cards/{id}","summary":"Update a job.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","workRequested":"Replace element, thermostat and drip tray","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","notes":"Budget deferred to the next financial year.","serialId":"5c2d8e14-6f3a-4b97-a0d1-7e9f2c4b6a18","serialNumber":"CB-24-0007"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}","summary":"Delete a job.","auth":"jwt","responseExample":{"status":"deleted"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/status","summary":"Move a job through open, in progress, awaiting parts, ready to invoice, closed.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"status":"awaiting_parts","note":"Budget deferred to the next financial year.","clientId":"9b2e4f61-7c3a-4d58-8e10-5a6b7c8d9e0f"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/summary","summary":"The board's tiles. Windowed to twelve months plus every open job.","auth":"jwt","responseExample":{"openJobs":1,"scheduledToday":1,"awaitingParts":1,"completedNotInvoiced":1,"wipValue":10005.0,"wipCost":10005.0,"invoicedThisMonth":1.0,"averageMarginPercent":15.0,"windowMonths":12,"currency":"ZAR"},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/{id}/labour","summary":"Book labour. The rates default from users.default_charge_rate and default_cost_rate — before those existed, cost_rate defaulted to zero and every job reported 100% margin.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-30","hours":2.0,"chargeRate":650.0,"costRate":320.0,"billable":true,"notes":"Budget deferred to the next financial year.","basis":"hours","units":null,"unitLabel":null,"earningTypeId":null},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/{id}/labour/{lineId}","summary":"Correct a labour line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":4.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","basis":"hours","units":null,"unitLabel":null,"earningTypeId":null},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}/labour/{lineId}","summary":"Remove a labour line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/labour/import-time","summary":"Pull hours in from time tracking. Imports only APPROVED entries — the project invoicer always required it and this path did not, so approvals were bypassed by whichever of the two billing paths somebody used.","auth":"jwt","responseExample":{"imported":1,"skipped":1},"body":{"timeEntryIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"chargeRate":15.0,"costRate":15.0},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/parts","summary":"Add a part to the job, before it is issued.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Captured during the August review","partCode":"CT-001","qty":2.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/{id}/parts/{lineId}","summary":"Change a part line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":2.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}/parts/{lineId}","summary":"Remove a part line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/parts/{lineId}/issue","summary":"Issue the part from stock at batch cost. What is in the van is out of the storeroom in the figures as well as in fact.","auth":"jwt","body":{"clientId":"9b2e4f61-7c3a-4d58-8e10-5a6b7c8d9e0f"},"responseExample":{"status":"issued","qtyIssued":3,"unitCost":"text","balanceAfter":"text","warning":"text","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","locationSource":"referral","locationMessage":"Saved."},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/parts/{lineId}/return","summary":"Return an unused part to stock.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/costs","summary":"Add an on-cost typed by hand — a subcontractor, a callout fee.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"costType":"other","description":"Crane hire","amount":4200.0,"markupPercent":10.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","incurredOn":"2026-09-01"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/costs/allocate","summary":"Allocate a real expense or bill to the job. JobCostAllocation is the single writer of both halves — the column on the purchase and the mirroring cost line — because either alone is a defect with a plausible screen.","auth":"jwt","responseExample":{"allocated":1,"skipped":["text"],"card":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]}},"body":{"expenseIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"billIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"billable":true,"markupPercent":15.0,"costType":"subcontractor"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/{id}/costs/{lineId}","summary":"Change a cost line. An allocated purchase's AMOUNT is refused here and the response names where to correct it — what a job cost is a fact about the purchase; what the customer is charged is a decision about the job, so markup and billable stay editable.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"costType":"other","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":20.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","incurredOn":"2026-09-01"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}/costs/{lineId}","summary":"Remove a cost line.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/allocatable-costs?search=cape","summary":"Expenses and bills that could still be allocated to a job.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","reference":"INV-0001","description":"Consulting services — August 2026","vendor":"Karoo Fresh Holdings Ltd","date":"2026-09-01","amount":10005.0,"currency":"ZAR","status":"sent","category":"Office supplies","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/pay-types","summary":"The per-unit payroll earning types a labour line counted in units can be paid as (e.g. Bay installed). Names only, never a rate, so a job-cards role without payroll access can choose one.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Bay installed","unitLabel":"bay"}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/technicians","summary":"Who can be assigned, with their default rates.","auth":"jwt","responseExample":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","defaultChargeRate":15.0,"defaultCostRate":15.0,"defaultStockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultStockLocationName":"Karoo Fresh Holdings Ltd"}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"PUT","path":"/api/job-cards/technicians/{userId}/rates","summary":"Set a person's default charge and cost rates. Deliberately NOT a per-project-per-person rate table — users owns the figure for both modules.","auth":"jwt","responseExample":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","defaultChargeRate":15.0,"defaultCostRate":15.0,"defaultStockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultStockLocationName":"Karoo Fresh Holdings Ltd"},"body":{"defaultChargeRate":650.0,"defaultCostRate":320.0,"clearChargeRate":false,"clearCostRate":false,"defaultStockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clearStockLocation":false},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/technicians","summary":"Assign a technician to the job.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isLead":false},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}/technicians/{userId}","summary":"Unassign a technician.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/sign-off","summary":"Capture the customer's signature. The strokes become a 1-bit PNG in object storage as an AttachmentKind.SIGNATURE — never base64 into the column, which tenantStorageBytes does not count.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"body":{"signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"<base64 PNG>","signOffNotes":"Budget deferred to the next financial year.","complete":true,"clientId":"9b2e4f61-7c3a-4d58-8e10-5a6b7c8d9e0f"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/convert","summary":"Raise the invoice — the final one, or a deposit or progress stage that leaves the job open (stage, percent or lineIds); the final deducts each percentage stage. Charges the VAT the tenant may actually charge — a company with no vat_number is not registered, and part lines bill at their own product's rate rather than a flat 15%.","auth":"jwt","responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","linesCreated":1,"total":10005.0,"currency":"ZAR","stage":"deposit"},"body":{"override":false,"issueDate":"2026-08-26","paymentTermsDays":30,"vatRate":15.0,"summariseLabour":false,"stage":"deposit","percent":30.0,"lineIds":[]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/{id}/report","summary":"The customer's job report — what was done, what was used, and the signature.","auth":"jwt","responseKind":"html","module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/checklist-templates","summary":"The company's checklist templates: each job type's required items and certificate title.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard","required":true}],"certificateTitle":"Karoo Fresh Holdings Ltd"}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/checklist-templates","summary":"Create a checklist template. Each item is a tick, text, a number or a photo, and required unless it says not.","auth":"jwt","body":{"name":"Gas safety","certificateTitle":"Gas Installation Certificate of Compliance","items":[{"label":"Isolation valve fitted","kind":"tick"},{"label":"Gas pressure (kPa)","kind":"number"},{"label":"Customer briefed","kind":"tick","required":false}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard","required":true}],"certificateTitle":"Karoo Fresh Holdings Ltd"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/checklist-templates/{templateId}","summary":"Change a checklist template. A job that already carries it keeps the items it was given.","auth":"jwt","body":{"name":"Gas safety","certificateTitle":"Gas Installation Certificate of Compliance","items":[{"label":"Isolation valve fitted","kind":"tick"},{"label":"Gas pressure (kPa)","kind":"number"}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard","required":true}],"certificateTitle":"Karoo Fresh Holdings Ltd"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/checklists","summary":"Put a template's checklist on a job. A required item left open stops the job being completed.","auth":"jwt","body":{"templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","basis":"invoice","units":1.0,"unitLabel":"Karoo Fresh Holdings Ltd","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Karoo Fresh Holdings Ltd"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"subcontractor","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"before","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"checklists":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","certificateTitle":"Karoo Fresh Holdings Ltd","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard","required":true,"ticked":false,"value":"text","answeredBy":"text","answeredAt":"2026-09-01T09:15:00Z"}]}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/{id}/checklists/{checklistId}/items/{key}","summary":"Answer one checklist item: tick it, or give its text, number or the id of one of the job's photographs.","auth":"jwt","body":{"ticked":false,"value":"2.8"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","basis":"invoice","units":1.0,"unitLabel":"Karoo Fresh Holdings Ltd","earningTypeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","earningTypeName":"Karoo Fresh Holdings Ltd"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"subcontractor","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"before","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"checklists":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","templateId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","certificateTitle":"Karoo Fresh Holdings Ltd","items":[{"key":"text","label":"Karoo Fresh Holdings Ltd","kind":"standard","required":true,"ticked":false,"value":"text","answeredBy":"text","answeredAt":"2026-09-01T09:15:00Z"}]}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/{id}/checklists/{checklistId}/certificate","summary":"A checklist's certificate: its answered items under the template's certificate title.","auth":"jwt","responseKind":"html","module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/{id}/on-the-way","summary":"The technician is on the way: tell the job's customer by email and WhatsApp, once per visit. Says what was sent, what was already sent for this visit, or why nobody could be told.","auth":"jwt","body":{"etaMinutes":20},"responseExample":{"sent":["text"],"alreadyTold":["text"],"nothingBecause":"text"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/{id}/report/send","summary":"Email the customer their signed job report, with the PDF attached.","auth":"jwt","body":{"email":"accounts@coastalcold.example"},"responseExample":{"sent":true,"to":"2026-09-30","attached":true,"message":"Saved."},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/dispatch?window=30&date=2027-02-28","summary":"The dispatcher's day or week - a lane per technician, work placed by the clock, clashes flagged. Layout is computed by shared/domain/jobcards/DispatchBoard.kt so the screen cannot paint an overlap the server would not see. window=day|week, date=ISO anchor; an unknown window is refused rather than widened.","auth":"jwt","responseExample":{"window":"text","fromDate":"2026-09-01","toDate":"2026-09-01","lanes":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"jobs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","title":"Karoo Fresh Holdings Ltd","status":"sent","priority":"normal","contactName":"Karoo Fresh Holdings Ltd","siteAddress":"12 Long Street, Cape Town, 8001","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","technicianIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]}],"unscheduledTotal":42},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/{id}/dispatch","summary":"Reschedule and reassign in ONE write - what a drag across the board is. Two calls would leave a job at a time nobody chose when the second failed. unassignUserId is what makes a drag out of a lane take the job off THAT technician only.","auth":"jwt","body":{"scheduledStart":"2026-08-27T08:00:00","scheduledEnd":"2026-08-27T10:00:00","assignUserId":"00000000-0000-0000-0000-000000000000","unassignUserId":"00000000-0000-0000-0000-000000000000"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"GET","path":"/api/job-cards/stock-locations","summary":"The stock locations the van picker may offer. Served here on jobcards:view because a role holding only jobcards:* cannot call the inventory tree at all - the same reason /api/bom/products exists.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","type":"standard","isVan":false}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/reports/wip","summary":"Work in progress — cost incurred and not yet billed. On a bad month it is most of a business's cash.","auth":"jwt","responseExample":{"rows":[{"jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","title":"Karoo Fresh Holdings Ltd","contactName":"Karoo Fresh Holdings Ltd","status":"sent","ageDays":30,"cost":10005.0,"billable":1.0}],"totalCost":10005.0,"totalBillable":10005.0,"currency":"ZAR"},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/reports/profitability?groupBy=job&dateFrom=2026-03-01&dateTo=2027-02-28&includeCancelled=true","summary":"Margin per job, measured against quotedAmount where the job came from an accepted quote.","auth":"jwt","responseExample":{"groupBy":"text","rows":[{"key":"text","label":"Karoo Fresh Holdings Ltd","jobCount":3,"quoted":1.0,"cost":10005.0,"billable":1.0,"margin":1.0,"marginPercent":15.0,"hours":3.0}],"totalCost":10005.0,"totalBillable":10005.0,"totalMargin":10005.0,"currency":"ZAR"},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/reports/sla?groupBy=customer&dateFrom=2026-12-01&dateTo=2026-12-31","summary":"SLA met: each customer's (or technician's) jobs logged under a contract with targets, and how many met their response and resolution targets.","auth":"jwt","responseExample":{"groupBy":"text","dateFrom":"2026-09-01","dateTo":"2026-09-30","rows":[{"key":"text","name":"Karoo Fresh Holdings Ltd","jobs":1,"respondMet":1,"respondBreached":1,"resolveMet":1,"resolveBreached":1}]},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/reports/by-status","summary":"Jobs by state, for the board's counts.","auth":"jwt","responseExample":{"rows":[{"status":"sent","label":"Karoo Fresh Holdings Ltd","count":3,"billableValue":10005.0}],"total":42,"currency":"ZAR"},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/reports/completion-time","summary":"How long jobs take, from raised to closed.","auth":"jwt","responseExample":{"sampleSize":1,"averageDaysToComplete":1.0,"averageDaysToInvoice":1.0,"medianDaysToComplete":1.0,"slowest":[{"jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","title":"Karoo Fresh Holdings Ltd","contactName":"Karoo Fresh Holdings Ltd","status":"sent","ageDays":30,"cost":10005.0,"billable":1.0}]},"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"GET","path":"/api/job-cards/{id}/photos","summary":"The job's photographs. Ids, not bytes — fetch each through /api/files/{id}, because a job with twenty pictures would otherwise make this response tens of megabytes on a phone at a kerbside.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/{id}/photos?phase=before&caption=Board+before+work&clientId=9b2e4f61-7c3a-4d58-8e10-5a6b7c8d9e0f","summary":"Attach a photograph. RAW BYTES, not base64 — a Compose camera hands the client a ByteArray on every target and base64 inflates a 4 MB photo by a third. An 'after' is refused while the job is draft or scheduled: it is almost always a mis-tagged before. Capped at 24 per job.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/{id}/photos/{photoId}","summary":"Unlink a photograph. Removes the LINK, not the stored file — a job-card screen is not where somebody should be able to destroy evidence.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","status":"sent","scheduledStart":"2026-09-01","scheduledEnd":"2026-09-30","actualStart":"2026-09-01","actualEnd":"2026-09-30","quotedAmount":10005.0,"currency":"ZAR","sourceQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceQuoteNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","invoicedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","signOffName":"Karoo Fresh Holdings Ltd","signOffRole":"Accountant","signOffSignature":"text","signOffSignatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","signOffNotes":"Budget deferred to the next financial year.","signOffAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year.","createdAt":"2026-09-01T09:15:00Z","technicians":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","isLead":false}],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","technicianName":"Thandi Mokoena","workDate":"2026-09-01","hours":3.0,"chargeRate":15.0,"costRate":15.0,"billable":true,"notes":"Budget deferred to the next financial year.","timeEntryId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"parts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","partCode":"CT-001","qty":3.0,"unitCost":2900.0,"unitPrice":2900.0,"billable":true,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","issued":false,"issuedAt":"2026-09-01T09:15:00Z","issuedQty":3.0,"stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockTracked":false}],"costs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costType":"standard","description":"Consulting services — August 2026","amount":10005.0,"markupPercent":15.0,"km":1.0,"ratePerKm":1.0,"billable":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","incurredOn":"2026-09-01","sourceExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceBillId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceReference":"INV-0001"}],"statusHistory":[{"fromStatus":"sent","toStatus":"sent","note":"Budget deferred to the next financial year.","changedByName":"Karoo Fresh Holdings Ltd","at":"2026-09-01T09:15:00Z"}],"photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","phase":"text","caption":"Serial plate before fitting","sequence":1,"takenByName":"Karoo Fresh Holdings Ltd","takenAt":"2026-09-01T09:15:00Z"}],"costing":{"labourHours":3.0,"labourCost":10005.0,"labourBillable":1.0,"partsCost":10005.0,"partsBillable":1.0,"otherCost":10005.0,"otherBillable":1.0,"actualCost":10005.0,"billableValue":10005.0,"quotedAmount":10005.0,"quoteVariance":1.0,"margin":1.0,"marginPercent":15.0},"allowedNextStatuses":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"}]},{"name":"Service contracts","blurb":"A cadence and an anchor date that raise ORDINARY job cards when a visit falls due. The contract owns no price: what a visit costs is a fact about the job card raised for it, priced the one way every job card is. Month stepping tracks the anchor, not the last clamp, so a 31st anchor gives 31 Jan / 28 Feb / 31 Mar.","endpoints":[{"method":"GET","path":"/api/job-cards/maintenance","summary":"The tenant's contracts, with the next due date and the number of visits owed COMPUTED server-side by MaintenanceSchedule — the same object the generator uses, so the countdown cannot disagree with the date a job card appears on.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadUserName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueOn":"2026-09-01","visitsOwed":1,"visitsRaised":1,"notes":"Budget deferred to the next financial year."}],"module":"job-cards","plan":"Business","scope":"job-cards:read"},{"method":"POST","path":"/api/job-cards/maintenance","summary":"Set up a contract. An unknown cadence is refused rather than defaulted: guessing would put a customer's quarterly inspection on a weekly footing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadUserName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueOn":"2026-09-01","visitsOwed":1,"visitsRaised":1,"notes":"Budget deferred to the next financial year."},"body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Monthly generator service","workRequested":"Quarterly service of the cold-room compressor","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","cadence":"monthly","anchorDate":"2026-01-31","endsOn":"2026-09-01","active":true,"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","serialId":"5c2d8e14-6f3a-4b97-a0d1-7e9f2c4b6a18","serialNumber":"CB-24-0007","slaTargets":{"urgent":{"respondMinutes":60,"resolveMinutes":480}},"businessHours":{"open":"08:00","close":"17:00","days":[1,2,3,4,5],"skipPublicHolidays":true}},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"PUT","path":"/api/job-cards/maintenance/{id}","summary":"Change a contract. active=false pauses it — it raises nothing whatever its dates say, and keeps its history.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","workRequested":"text","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","leadUserName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueOn":"2026-09-01","visitsOwed":1,"visitsRaised":1,"notes":"Budget deferred to the next financial year."},"body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Monthly generator service","workRequested":"Quarterly service of the cold-room compressor","siteAddress":"12 Long Street, Cape Town, 8001","siteContactName":"Karoo Fresh Holdings Ltd","siteContactPhone":"+27 82 555 0143","priority":"normal","cadence":"monthly","anchorDate":"2026-01-31","endsOn":"2026-09-01","active":false,"leadUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","serialId":"5c2d8e14-6f3a-4b97-a0d1-7e9f2c4b6a18","serialNumber":"CB-24-0007","slaTargets":{"urgent":{"respondMinutes":60,"resolveMinutes":480}},"businessHours":{"open":"08:00","close":"17:00","days":[1,2,3,4,5],"skipPublicHolidays":true}},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"DELETE","path":"/api/job-cards/maintenance/{id}","summary":"End a contract. Does not touch the job cards it has already raised — those are real work, some of it invoiced.","auth":"jwt","responseExample":{"status":"deleted"},"module":"job-cards","plan":"Business","scope":"job-cards:write"},{"method":"POST","path":"/api/job-cards/maintenance/{id}/raise","summary":"Raise the visits this contract owes, now. EVERY owed visit, not just the newest: a monthly contract three visits behind owes three job cards. Idempotent by a partial unique index on (contract, due date), so two replicas cannot raise the same visit twice. The same code the maintenance-jobcards scheduled job runs.","auth":"jwt","responseExample":{"raised":1,"jobNumbers":["JC-0001"],"skipped":["text"]},"module":"job-cards","plan":"Business","scope":"job-cards:write"}]},{"name":"Time tracking","blurb":"The hours behind a job. rate_snapshot and cost_rate live on the ENTRY, because reading a project's live rate silently restated the value of every unbilled hour ever logged whenever a project was repriced.","endpoints":[{"method":"GET","path":"/api/time-tracking/entries?from=2026-08-01&to=2026-08-31&page=1&q=1","summary":"Time entries, server-paged and server-filtered. It used to return every entry the tenant had ever logged, with no limit and no filter, on every screen load.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectName":"Karoo Fresh Holdings Ltd","client":"text","description":"Consulting services — August 2026","workDate":"2026-09-01","hours":3.0,"billable":true,"approved":true,"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userName":"Thandi Mokoena","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobNumber":"JC-0001","task":"text","taskId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approvedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","rateSnapshot":1.0}],"total":42,"page":1,"limit":100,"totalPages":1},"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"POST","path":"/api/time-tracking/entries","summary":"Log time. Amounts accept what people paste — \"1 500,50\" and \"R1500.50\" both parse.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Captured during the August review","workDate":"2026-09-30","hours":2.0,"billable":true,"task":"Design","taskId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rate":850.0,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"PUT","path":"/api/time-tracking/entries/{id}","summary":"Correct an entry, so a mis-typed 8 hours need not be deleted and re-captured — and delete needs a permission capture does not.","auth":"jwt","responseExample":{"status":"updated"},"body":{"description":"Consulting services — August 2026","workDate":"2026-09-01","hours":6.0,"billable":true,"task":"Design","taskId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clearTaskId":false,"rate":15.0,"clearRate":false},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"DELETE","path":"/api/time-tracking/entries/{id}","summary":"Delete an entry. Refused once it is billed or held by a job card.","auth":"jwt","responseExample":{"status":"deleted"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"PUT","path":"/api/time-tracking/entries/{id}/approve","summary":"Approve one entry. Records who approved it and when — approval used to be a bare boolean with no actor, under an invoice to a customer.","auth":"jwt","body":{"approved":true},"responseExample":{"status":"sent"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/entries/approve","summary":"Approve many at once.","auth":"jwt","responseExample":{"approved":1,"skipped":["text"]},"body":{"entryIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"approved":true},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/entries/{id}/bill","summary":"Mark an entry billed. Refused for an entry a job card already holds.","auth":"jwt","body":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"status":"billed"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"GET","path":"/api/time-tracking/projects","summary":"Projects, with budget hours, budget amount and actuals against them.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hourlyRate":15.0,"billable":true,"active":true,"budgetHours":3.0,"budgetAmount":10005.0,"actualHours":3.0,"billableHours":3.0,"actualValue":10005.0,"unbilledValue":10005.0,"actualCost":10005.0,"disbursementCost":10005.0,"unbilledDisbursements":1.0,"billingType":"standard","fixedFee":1.0,"margin":1.0,"budgetUsedPercent":15.0,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memberUserIds":["8d2e4b17-0c3a-4f59-b6e2-91a7d5c3e804"],"anyoneCanLogTime":false}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"GET","path":"/api/time-tracking/settings","summary":"The time lock date and the hours a week each person is expected to log.","auth":"jwt","responseExample":{"lockDate":"2026-09-01","weeklyHours":3.0},"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"PUT","path":"/api/time-tracking/settings","summary":"Move the time lock date (time on or before it cannot be added, corrected or removed) and set the hours a week. Needs approve.","auth":"jwt","body":{"lockDate":"2026-09-30","weeklyHours":40.0},"responseExample":{"lockDate":"2026-09-01","weeklyHours":3.0},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"GET","path":"/api/time-tracking/reports/utilisation?dateFrom=2026-10-01&dateTo=2026-10-31","summary":"Utilisation per person for the period (at most a year): hours worked; approved billable and billed hours and the value of each at the rates recorded; available hours from the person's own hours a week, else the business's hours a week (weeklyHoursSource says which; with neither, availableHours and utilisation are null and availableReason says why); utilisation (approved billable ÷ available, in percent) and realisation — shown as the billed share — (billed value ÷ billable value, in percent; an invoice line reduced after it was raised is not reflected), with the unbilled value beside them; capacityHours and ofCapacity are kept for callers of the earlier shape. Needs timetracking:edit.","auth":"jwt","responseExample":{"dateFrom":"2026-10-01","dateTo":"2026-10-31","workingDays":22.0,"companyWeeklyHours":40.0,"rows":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","weeklyHours":40.0,"weeklyHoursSource":"person","availableHours":176.0,"hours":150.0,"billableHours":132.0,"billedHours":100.0,"billableValue":125400.0,"billedValue":95000.0,"unbilledValue":30400.0,"utilisation":75.0,"realisation":75.76,"capacityHours":176.0,"ofCapacity":85.23}],"totals":{"name":"Total","weeklyHours":40.0,"availableHours":176.0,"hours":150.0,"billableHours":132.0,"billedHours":100.0,"billableValue":125400.0,"billedValue":95000.0,"unbilledValue":30400.0,"utilisation":75.0,"realisation":75.76,"capacityHours":176.0,"ofCapacity":85.23},"hours":150.0,"billableHours":132.0,"utilisation":75.0},"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"GET","path":"/api/time-tracking/projects/{id}/milestones","summary":"A fixed-fee project's milestones and the invoice each is on.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","amount":10005.0,"dueDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"POST","path":"/api/time-tracking/projects/{id}/milestones","summary":"Add a milestone to a fixed-fee project; the milestones never come to more than the fee.","auth":"jwt","body":{"name":"Design signed off","amount":40000.0,"dueDate":"2026-11-30"},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","amount":10005.0,"dueDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/projects/{id}/milestones/{milestoneId}/invoice","summary":"Invoice a milestone (a draft, once); a voided invoice gives the milestone back.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","amount":10005.0,"dueDate":"2026-09-01","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001"}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/projects","summary":"Create a project. Whoever creates it owns it; time is logged on it by its owner, its members (memberUserIds), timetracking:edit, or anyone when anyoneCanLogTime is on (off unless sent).","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hourlyRate":15.0,"billable":true,"active":true,"budgetHours":3.0,"budgetAmount":10005.0,"actualHours":3.0,"billableHours":3.0,"actualValue":10005.0,"unbilledValue":10005.0,"actualCost":10005.0,"disbursementCost":10005.0,"unbilledDisbursements":1.0,"billingType":"standard","fixedFee":1.0,"margin":1.0,"budgetUsedPercent":15.0,"ownerUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","memberUserIds":[],"anyoneCanLogTime":false},"body":{"name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hourlyRate":15.0,"billable":true,"budgetHours":3.0,"budgetAmount":10005.0,"billingType":"standard","fixedFee":1.0,"anyoneCanLogTime":false,"memberUserIds":[]},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"PUT","path":"/api/time-tracking/projects/{id}","summary":"Update a project. Repricing changes future entries only — logged hours keep the rate they were logged at.","auth":"jwt","responseKind":"json","body":{"name":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hourlyRate":15.0,"billable":true,"active":true,"budgetHours":3.0,"budgetAmount":10005.0,"billingType":"standard","fixedFee":1.0,"clearBudgetHours":false,"clearBudgetAmount":false,"clearContactId":false,"anyoneCanLogTime":true,"memberUserIds":[]},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/projects/{id}/invoice","summary":"Invoice a project's approved, unbilled hours as service lines.","auth":"jwt","body":{"issueDate":"2026-08-31","terms":"30"},"responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","entriesBilled":1},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"GET","path":"/api/time-tracking/timer/active","summary":"The running timer, if there is one.","auth":"jwt","responseExample":{"timer":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","startedAtEpochMs":1,"billable":true}},"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"POST","path":"/api/time-tracking/timer/start","summary":"Start a timer.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","startedAtEpochMs":1,"billable":true},"body":{"projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"API work","taskId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"POST","path":"/api/time-tracking/timer/{id}/stop","summary":"Stop a timer and write the entry.","auth":"jwt","responseExample":{"status":"stopped"},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"GET","path":"/api/time-tracking/weekly-totals?week=2026-W34","summary":"The week's totals per person and per project.","auth":"jwt","responseExample":{"weekStart":"2026-09-01","totalHours":3.0,"billableHours":3.0,"unbilledRevenue":1.0},"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"GET","path":"/api/time-tracking/people","summary":"Everybody's standing charge-out and cost rates — what an hour defaults to when no task rate or typed rate applies. Needs timetracking:edit, the read as well as the write: a cost rate is close to what somebody is paid. A rate that is not set is null, never zero.","auth":"jwt","responseExample":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","defaultChargeRate":950.0,"defaultCostRate":420.0,"weeklyHours":40.0}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"PUT","path":"/api/time-tracking/people/{userId}/rates","summary":"Set or clear a person's standing rates from Time Tracking. The same figures, and the same writer, as the job-card technician rates — two doors, one owner. A null leaves a figure alone; clearChargeRate / clearCostRate / clearWeeklyHours empty it. weeklyHours is the person's standing working week (more than 0, at most 100, the same bound as the business's hours a week), and it beats the business's, which the utilisation report spreads over the period's working days.","auth":"jwt","responseExample":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thandi Mokoena","defaultChargeRate":950.0,"defaultCostRate":420.0,"weeklyHours":40.0},"body":{"defaultChargeRate":950.0,"defaultCostRate":420.0,"clearChargeRate":false,"clearCostRate":false,"weeklyHours":40.0,"clearWeeklyHours":false},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"GET","path":"/api/time-tracking/projects/{id}/tasks","summary":"Tasks on a project, with their charge and cost rates. `timetracking:view`.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","chargeRate":15.0,"costRate":15.0,"active":true,"sortOrder":1,"effectiveRate":15.0,"effectiveRateSource":"referral","loggedHours":3.0}],"module":"time-tracking","plan":"Starter","scope":"time-tracking:read"},{"method":"POST","path":"/api/time-tracking/projects/{id}/tasks","summary":"Add a task to a project. `timetracking:create`. A rate left null is 'not set' rather than zero — a zero cost rate reports a 100% margin.","auth":"jwt","body":{"name":"Site survey","chargeRate":950.0,"costRate":480.0,"active":true,"sortOrder":0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","projectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","chargeRate":15.0,"costRate":15.0,"active":true,"sortOrder":1,"effectiveRate":15.0,"effectiveRateSource":"referral","loggedHours":3.0},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"PUT","path":"/api/time-tracking/projects/{id}/tasks/{taskId}","summary":"Correct a task. `timetracking:edit`. Set clearChargeRate or clearCostRate to unset a rate: null cannot say 'unset'.","auth":"jwt","body":{"name":"Site survey","chargeRate":950.0,"costRate":480.0,"active":true,"sortOrder":0,"clearChargeRate":false,"clearCostRate":false},"responseKind":"json","module":"time-tracking","plan":"Starter","scope":"time-tracking:write"},{"method":"DELETE","path":"/api/time-tracking/projects/{id}/tasks/{taskId}","summary":"Remove a task. `timetracking:delete`.","auth":"jwt","responseExample":{"retired":true,"message":"Saved."},"module":"time-tracking","plan":"Starter","scope":"time-tracking:write"}]},{"name":"Workflows","blurb":"Boards of work items — a month-end close, a client onboarding, an engineering change, a non-conformance. The one module with NO financial consequence: it posts nothing, moves no stock, mints no document number and raises no invoice, which is why a finished card can be dragged back out of Done where an invoiced job card cannot move at all. Hours logged on a card are ordinary `time_entries` rows carrying `workflow_item_id`, so the board feeds the client's matter without anybody re-keying anything.","endpoints":[{"method":"GET","path":"/api/workflows/templates","summary":"The five board templates the new-board dialog offers, each with its columns and the stage every column maps to. Data in `shared`, not rows: a template is read once at creation and the board owns its columns from that moment.","auth":"jwt","responseExample":{"templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","suggestedPrefix":"INV-","columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","position":1,"wipLimit":50,"count":3}]}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"GET","path":"/api/workflows/members","summary":"People a card can be assigned to. Four fields, not the user row — this fills a dropdown, and shipping roles, sessions and 2FA state to do that is the unbounded-list problem with a new name.","auth":"jwt","responseExample":{"members":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"GET","path":"/api/workflows/link-options?q=cape","summary":"Matters, customers and (for a practice) clients a board or a card can be linked to, and the periods, bank reconciliations, invoices and bills a close card can close (closesKind period | reconciliation | invoice | bill, closesId the record), as {id, name} pairs. Each list is bounded; ?q= narrows every list in SQL, invoices and bills by number or customer/supplier. Served here rather than from /api/time-tracking/projects and /api/contacts for the reason /api/bom/products exists: a role holding only workflows:* cannot call either, so the picker would be empty for exactly the person whose screen it is. Hours logged on a card become time entries against the matter this names.","auth":"jwt","responseExample":{"projects":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"contacts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"clients":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"periods":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"reconciliations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"invoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"bills":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"GET","path":"/api/workflows/boards?archived=true","summary":"Every board this company can see, with its columns and live counts. A board with no company is visible to all of them — the cost_centres shape. Archived boards are excluded unless asked for.","auth":"jwt","responseExample":{"boards":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","description":"Consulting services — August 2026","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","archived":true,"columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","position":1,"wipLimit":50,"count":3}],"itemCount":3,"openCount":3,"createdAt":"2026-09-01T09:15:00Z"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"POST","path":"/api/workflows/boards","summary":"Create a board from a template. The prefix is normalised upper case and must be free across the tenant, because it is half of every item number people quote to each other.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","description":"Consulting services — August 2026","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","archived":false,"columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","position":1,"wipLimit":50,"count":3}],"itemCount":3,"openCount":3,"createdAt":"2026-09-01T09:15:00Z"},"body":{"name":"Month-end close","keyPrefix":"CLOSE","description":"Reconciliations and reviews for one period","templateId":"month-end","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"todo","wipLimit":50,"gate":false}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/boards/{id}","summary":"One board, with its columns and their live counts.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","description":"Consulting services — August 2026","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","archived":false,"columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","position":1,"wipLimit":50,"count":3}],"itemCount":3,"openCount":3,"createdAt":"2026-09-01T09:15:00Z"},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"PUT","path":"/api/workflows/boards/{id}","summary":"Rename, re-point or archive a board, and save its columns as a WHOLE list. Whole-list because reorder, rename, add and remove happen in one dialog — four endpoints would let a board be saved with a column deleted and its replacement not yet added. A column still holding cards is refused, never orphaned.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","keyPrefix":"INV-","description":"Consulting services — August 2026","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","archived":false,"columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","position":1,"wipLimit":50,"count":3}],"itemCount":3,"openCount":3,"createdAt":"2026-09-01T09:15:00Z"},"body":{"name":"Month-end close","description":"Reconciliations and reviews","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","archived":false,"columns":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Not started","stage":"todo","wipLimit":50,"gate":false},{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"In progress","stage":"in_progress","wipLimit":5,"gate":false}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/boards/{id}","summary":"Delete an EMPTY board. One still holding cards is refused with the count and told to archive instead — deleting would strand their comments, their history and any hours logged against them.","auth":"jwt","responseKind":"none","module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/boards/{id}/items?q=is%3Aoverdue+p%3Aurgent&offset=0","summary":"The board's cards. `q` is the board's filter language — `is:` `stage:` `column:` `type:` `priority:` `label:` `assignee:` `for:` `due:` plus bare words, same key OR, different keys AND. Parsed by one object in `shared` so the client and the server cannot disagree about what `a:me` means.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stage":"text","columnName":"Karoo Fresh Holdings Ltd","itemKey":"text","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","reporterUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reporterName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","estimateMinutes":1,"loggedMinutes":1,"dueDate":"2026-09-01","rank":1.0,"startedAt":"2026-09-01T09:15:00Z","closedAt":"2026-09-01T09:15:00Z","commentCount":3,"attachmentCount":3,"recurrenceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","recurrenceName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"total":42,"limit":50,"offset":0},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"GET","path":"/api/workflows/boards/{id}/insights","summary":"Flow. Work in progress against each column's limit, throughput per week, and cycle time as a MEDIAN plus the 85th percentile — a mean over one card that waited four months for a supplier reports a typical card as taking three weeks, which is true of nothing on the board.","auth":"jwt","responseExample":{"boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","total":42,"open":1,"wip":1,"blocked":1,"overdue":1,"dueThisWeek":1,"unassigned":1,"columns":[{"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","count":3,"limit":50,"over":false}],"breaches":[{"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stage":"text","count":3,"limit":50,"over":false}],"completedInWindow":1,"cancelledInWindow":1,"throughputPerWeek":1.0,"medianCycleDays":30,"p85CycleDays":30,"medianQueueDays":30,"oldestOpenDays":30,"windowDays":28,"byAssignee":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","open":1,"overdue":1}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"GET","path":"/api/workflows/boards/{id}/export","summary":"The board as CSV. Gated on workflows:export.","auth":"jwt","responseKind":"csv","module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"POST","path":"/api/workflows/items","summary":"Raise a card. The item number comes off the board's own counter taken FOR UPDATE, never count(*), which reissues a number the moment anything is deleted. A card inherits the board's matter unless it names its own.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stage":"text","columnName":"Karoo Fresh Holdings Ltd","itemKey":"text","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","reporterUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reporterName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","estimateMinutes":1,"loggedMinutes":1,"dueDate":"2026-09-01","rank":1.0,"startedAt":"2026-09-01T09:15:00Z","closedAt":"2026-09-01T09:15:00Z","commentCount":3,"attachmentCount":3,"recurrenceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","recurrenceName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Reconcile the FNB cheque account","description":"Statement to 31 August","itemType":"task","priority":"high","labels":["vat","fnb"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","estimateMinutes":120,"dueDate":"2026-09-07","closesKind":"reconciliation","closesId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/items/{id}","summary":"One card with its comments, its history and the time logged against it. The history is read from `audit_log` rather than a second trail, so “who moved this card” has one answer. The individual time entries are included only for a caller holding timetracking:view.","auth":"jwt","responseExample":{"item":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stage":"text","columnName":"Karoo Fresh Holdings Ltd","itemKey":"text","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","reporterUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reporterName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","lotNumber":"INV-0001","clientName":"Karoo Fresh Holdings Ltd","estimateMinutes":1,"loggedMinutes":1,"dueDate":"2026-09-01","rank":1.0,"startedAt":"2026-09-01T09:15:00Z","closedAt":"2026-09-01T09:15:00Z","commentCount":3,"attachmentCount":3,"recurrenceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","recurrenceName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"comments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","createdAt":"2026-09-01T09:15:00Z"}],"activity":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","action":"created","actorName":"Karoo Fresh Holdings Ltd","detail":"Saved.","createdAt":"2026-09-01T09:15:00Z"}],"timeEntries":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userName":"Thandi Mokoena","minutes":1,"description":"Consulting services — August 2026","entryDate":"2026-09-01","billable":true,"approved":false}],"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}],"checklist":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","done":false,"doneAt":"2026-09-01T09:15:00Z","doneByName":"Karoo Fresh Holdings Ltd"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"PUT","path":"/api/workflows/items/{id}","summary":"Edit a card. Every field optional; null leaves it alone and “” clears it — the three-state convention bills.purchase_order_id established, so a caller learns one rule rather than two.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stage":"text","columnName":"Karoo Fresh Holdings Ltd","itemKey":"text","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","reporterUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reporterName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","estimateMinutes":1,"loggedMinutes":1,"dueDate":"2026-09-01","rank":1.0,"startedAt":"2026-09-01T09:15:00Z","closedAt":"2026-09-01T09:15:00Z","commentCount":3,"attachmentCount":3,"recurrenceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","recurrenceName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"title":"Reconcile the FNB cheque account","description":"Statement to 31 August","itemType":"task","priority":"urgent","labels":["vat"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"","timeProjectId":"","estimateMinutes":180,"dueDate":"2026-09-07","closesKind":"period","closesId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/items/{id}","summary":"Soft-delete a card. Owner and Admin only by default.","auth":"jwt","responseKind":"none","module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"POST","path":"/api/workflows/items/{id}/move","summary":"A drag. `insertIndex` rather than a rank: the client knows where the card landed between its neighbours and the server owns what number that becomes, so the fractional-index arithmetic — including renumbering an exhausted gap — lives on one side of the wire. A column at its work-in-progress limit refuses with a 409 naming the count and the limit.","auth":"jwt","responseExample":{"item":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stage":"text","columnName":"Karoo Fresh Holdings Ltd","itemKey":"text","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","reporterUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reporterName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","timeProjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","timeProjectName":"Karoo Fresh Holdings Ltd","estimateMinutes":1,"loggedMinutes":1,"dueDate":"2026-09-01","rank":1.0,"startedAt":"2026-09-01T09:15:00Z","closedAt":"2026-09-01T09:15:00Z","commentCount":3,"attachmentCount":3,"recurrenceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","recurrenceName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"warning":"text","rebalanced":false},"body":{"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","insertIndex":0},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"POST","path":"/api/workflows/items/{id}/checklist","summary":"Add a step to the checklist inside a card; answers the card's checklist.","auth":"jwt","body":{"label":"Agree the output tax to the ledger"},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","done":false,"doneAt":"2026-09-01T09:15:00Z","doneByName":"Karoo Fresh Holdings Ltd"}],"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"PUT","path":"/api/workflows/checklist/{id}","summary":"Tick or untick a checklist step (done), or rename it (label); answers the card's checklist.","auth":"jwt","body":{"done":true,"label":"Agree the output tax to the ledger"},"responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","done":false,"doneAt":"2026-09-01T09:15:00Z","doneByName":"Karoo Fresh Holdings Ltd"}],"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/checklist/{id}","summary":"Remove a step from a card's checklist.","auth":"jwt","responseKind":"none","module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"POST","path":"/api/workflows/items/{id}/comments","summary":"Comment on a card.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","createdAt":"2026-09-01T09:15:00Z"},"body":{"body":"Bank has sent the missing statement.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/comments/{id}","summary":"Soft-delete a comment.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","authorName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","createdAt":"2026-09-01T09:15:00Z"},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"POST","path":"/api/workflows/items/{id}/time","summary":"Log time against a card as a `time_entries` row. Gated on timetracking:create, NOT workflows:edit — the resource a permission names is the thing being written, never the screen it was written from. Refused when neither the card nor its board is linked to a project: time_entries.project_id is NOT NULL and picking one on the user's behalf would attribute somebody's afternoon to a client who never asked for it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userName":"Thandi Mokoena","minutes":1,"description":"Consulting services — August 2026","entryDate":"2026-09-01","billable":true,"approved":false},"body":{"minutes":90,"description":"Cleared the September reconciling items","entryDate":"2026-09-02","billable":true,"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/items/{id}/attachments","summary":"The files filed against one card, each with a signed URL minted for this read and never stored. A file that cannot be signed comes back with a null URL rather than being hidden — one unsignable file must not make the other four disappear.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"POST","path":"/api/workflows/items/{id}/attachments?filename=brief.pdf&caption=Serial%20plate%20before%20fitting&contentType=application%2Fpdf","summary":"Attach a file to a card. Raw BYTES with the name on the query string, not multipart and not base64 — base64 inflates a 4 MB scan by a third on exactly the connection this product is designed for. The declared content type is a hint used only to accept or refuse; what is stored comes from the closed list in `AttachableFile`. Twelve files a card, 15 MB each. Gated on `workflows:edit`, not `create`: the file nearly always goes onto a card that already exists.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/items/{id}/attachments/{linkId}","summary":"Unlink a file. Removes the LINK, never the bytes — the same attachment may be referenced from an expense or a sales document, and a board is not a place from which somebody should be able to destroy a receipt the books depend on. Deleting the file itself is DELETE /api/files/{id}.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/recurrences?boardId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Recurring checklists — the work that comes round again. Each carries its cadence, its next due date in words (never blank: \"Paused\" and \"Finished\" are answers) and the cards it raises.","auth":"jwt","responseExample":{"recurrences":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueLabel":"Karoo Fresh Holdings Ltd","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","estimateMinutes":1,"dueOffsetDays":30,"position":1}]}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"POST","path":"/api/workflows/recurrences","summary":"Set up a checklist that raises itself. A month-end close is fourteen cards, not one, so the recurrence owns a LIST; each occurrence raises them as ordinary cards with nothing special about them afterwards. The cadence arithmetic is `MaintenanceSchedule`, shared with service contracts rather than copied, so a 31st anchor gives 31 Jan then 28 Feb then 31 Mar.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueLabel":"Karoo Fresh Holdings Ltd","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","estimateMinutes":1,"dueOffsetDays":30,"position":1}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"GET","path":"/api/workflows/recurrences/{id}","summary":"One recurring checklist with its cards, in the shape the editor saves — a dialog that saves what it loaded has to load what it saves.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueLabel":"Karoo Fresh Holdings Ltd","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","estimateMinutes":1,"dueOffsetDays":30,"position":1}]},"module":"workflows","plan":"Enterprise","scope":"workflows:read"},{"method":"PUT","path":"/api/workflows/recurrences/{id}","summary":"Edit a checklist. A line that keeps its id keeps its identity, and that is load-bearing: the idempotency key is (line, occurrence), so a line re-created with a fresh id would raise its card again for an occurrence already dealt with.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","boardName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","anchorDate":"2026-09-01","endsOn":"2026-09-01","active":true,"columnId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","columnName":"Karoo Fresh Holdings Ltd","lastRaisedOn":"2026-09-01","nextDueLabel":"Karoo Fresh Holdings Ltd","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","itemType":"standard","priority":"normal","labels":["Karoo Fresh Holdings Ltd"],"assigneeUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assigneeName":"Thandi Mokoena","estimateMinutes":1,"dueOffsetDays":30,"position":1}]},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"DELETE","path":"/api/workflows/recurrences/{id}","summary":"Stop a checklist recurring. The cards it has already raised STAY — they are ordinary work somebody may be halfway through. Pausing is the reversible option and the list says so.","auth":"jwt","responseExample":{"cardsLeftStanding":1},"module":"workflows","plan":"Enterprise","scope":"workflows:write"},{"method":"POST","path":"/api/workflows/recurrences/{id}/raise","summary":"Raise everything this checklist owes, now — the same implementation the `workflow-recurrences` job runs, because a button with its own version would eventually raise a different set from the timer. Reports occurrences raised AND occurrences passed over as older than the backfill window: a run that reported only what it did would be indistinguishable from one that found nothing owed.","auth":"jwt","responseExample":{"raised":1,"cards":1,"occurrences":["text"],"skipped":["text"],"alreadyRaised":1,"note":"Budget deferred to the next financial year."},"module":"workflows","plan":"Enterprise","scope":"workflows:write"}]},{"name":"Rental & hire","blurb":"The hire register. Every item or pool is one fixed asset — the hire fleet is never stock — and its units are split between the yard, booked, on hire, in service and lost. Only a contract, a service or a write-off moves a unit; the item's own door edits its name, class and size and never a count. Licensed by the Rental & Hire add-on (from Business), gated on the `rental` permission.","endpoints":[{"method":"GET","path":"/api/rental/items","summary":"The hire register for the active company: every item and pool by name, with where its units are today.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","itemClass":"text","kind":"standard","quantity":3,"available":1,"reserved":1,"onHire":1,"inService":1,"lost":1,"status":"sent"}],"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"GET","path":"/api/rental/items/{id}","summary":"One item on the hire register.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","itemClass":"text","kind":"standard","quantity":3,"available":1,"reserved":1,"onHire":1,"inService":1,"lost":1,"status":"sent"},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"GET","path":"/api/rental/assets","summary":"Fixed assets of the active company that could go on the register: in use and not on it yet. Needs rental:create, not the ledger's own permission.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","assetClassLabel":"Karoo Fresh Holdings Ltd"}],"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"GET","path":"/api/rental/utilisation?from=2026-09-14&to=2026-10-13","summary":"What each item works and earns over a window (default the last 30 days): unit-days on hire over unit-days owned, its share of what its hire documents posted, its depreciation and its service cost, by item and by class. Idle items are flagged.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","items":[{"itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","itemClass":"text","assetNumber":"INV-0001","quantity":1,"daysOwned":30,"unitDaysOwned":30,"unitDaysOnHire":30,"utilisation":1.0,"income":1.0,"depreciation":1.0,"serviceCost":10005.0,"net":8700.0,"idle":true}],"classes":[{"itemClass":"text","items":1,"unitDaysOwned":30,"unitDaysOnHire":30,"utilisation":1.0,"income":1.0,"depreciation":1.0,"serviceCost":10005.0,"net":8700.0}],"totals":{"itemClass":"text","items":1,"unitDaysOwned":30,"unitDaysOnHire":30,"utilisation":1.0,"income":1.0,"depreciation":1.0,"serviceCost":10005.0,"net":8700.0}},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"POST","path":"/api/rental/items","summary":"Register a fixed asset for hire, as one item (serial) or a pool of identical units. An asset is registered once; a disposed asset is refused.","auth":"jwt","body":{"fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"pool","quantity":120,"itemClass":"Scaffolding","name":"Plate compactor","meterUnit":"hours","meterReading":210.0,"serviceEvery":250.0,"serviceEveryDays":180,"replacementValue":18500.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","itemClass":"text","kind":"standard","quantity":3,"available":1,"reserved":1,"onHire":1,"inService":1,"lost":1,"status":"sent"},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"PATCH","path":"/api/rental/items/{id}","summary":"Rename, re-class or resize an item. A pool cannot shrink below the units booked, out, in service or lost; the counts themselves are not editable here.","auth":"jwt","body":{"name":"Scaffold frame 2 m","quantity":140,"itemClass":"Compaction","replacementValue":18000.0,"meterUnit":"hours","meterReading":210.0,"serviceEvery":250.0,"serviceEveryDays":180},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","assetNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","itemClass":"text","kind":"standard","quantity":3,"available":1,"reserved":1,"onHire":1,"inService":1,"lost":1,"status":"sent"},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"DELETE","path":"/api/rental/items/{id}","summary":"Take an item off the register. Refused while any unit is booked, out, in service or lost.","auth":"jwt","responseKind":"none","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/items/{id}/sell","summary":"Sell an ex-hire item, or some of a pool, from the yard: an invoice issued to the buyer at the sale, coded to Profit on Disposal, and the units' share of the fixed asset disposed of against the price, so the sale is one net gain or loss. The invoice cannot then be voided or deleted; a credit note is the way back. Never stock: 1310 is not touched. Refused while the units are booked, out or away. Needs rental:edit and invoices:create.","auth":"jwt","body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","price":12000.0,"units":1,"on":"2026-10-13"},"responseExample":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","bookValue":10005.0,"price":10005.0},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"GET","path":"/api/rental/settings","summary":"Which days of a hire the company charges: calendar, mon_fri or mon_sat (public holidays out on working days).","auth":"jwt","responseExample":{"chargeableDays":"text"},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"PUT","path":"/api/rental/settings","summary":"Set the chargeable-days rule. Needs rental:edit.","auth":"jwt","body":{"chargeableDays":"mon_fri"},"responseExample":{"chargeableDays":"text"},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"GET","path":"/api/rental/rate-cards","summary":"Every rate card of the active company — per item, or per class of items. An item's own card wins over its class's.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemClass":"text","day":1.0,"week":1.0,"fourWeek":1.0,"weekend":1.0,"minimumDays":1}],"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"PUT","path":"/api/rental/rate-cards","summary":"Create or replace the card for one item (hireItemId) or one class (itemClass) — exactly one. Rands per unit; week, four-week and weekend rates are optional.","auth":"jwt","body":{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","day":450.0,"week":1350.0,"minimumDays":1,"itemClass":"Compaction","fourWeek":3600.0,"weekend":700.0,"meterAllowancePerDay":8.0,"meterOverRate":150.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemClass":"text","day":1.0,"week":1.0,"fourWeek":1.0,"weekend":1.0,"minimumDays":1},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"DELETE","path":"/api/rental/rate-cards/{id}","summary":"Remove a rate card.","auth":"jwt","responseKind":"none","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/quote","summary":"Price a hire: the cheapest mix of four-week periods, weeks and days covering the chargeable days, per line, ex VAT. Writes nothing. An item with no card is refused by name.","auth":"jwt","body":{"out":"2026-10-05","offHire":"2026-10-13","lines":[{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":1}]},"responseExample":{"out":"text","offHire":"text","chargeableDays":"text","lines":[{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","quantity":3,"chargeableDays":30,"periods":"2026-09","perUnit":1.0,"total":10005.0}],"total":10005.0},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"GET","path":"/api/rental/items/{id}/availability?from=2026-10-05&to=2026-10-13","summary":"How many of an item are free on every day of from..to (the peak of the bookings on any one day), and the bookings around it.","auth":"jwt","responseExample":{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","from":"2026-09-01","to":"2026-09-30","quantity":3,"free":1,"bookings":[{"contractNumber":"INV-0001","from":"2026-09-01","to":"2026-09-30","quantity":3}]},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"GET","path":"/api/rental/contracts?status=out&limit=50","summary":"The company's hire contracts, newest first, at most 200; ?status=booked|out|off_hired|returned|cancelled narrows it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","offHireRequestedBy":"text","offHireRequestedAt":"2026-09-01T09:15:00Z","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09","meterUnit":"each","meterOut":1.0,"crossHired":false,"supplierName":"Karoo Fresh Holdings Ltd"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"depositHeld":1.0,"total":10005.0,"billing":"text","invoices":[{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","kind":"invoice","from":"2026-09-01","to":"2026-09-30","status":"sent","total":10005.0,"amountDue":10005.0}]}],"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"GET","path":"/api/rental/contracts/{id}","summary":"One contract: its lines (booked, out, back, missing, with the customer), the hire charge so far from HireCharge, inspection charges and logistics stops.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","offHireRequestedBy":"text","offHireRequestedAt":"2026-09-01T09:15:00Z","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09","meterUnit":"each","meterOut":1.0,"crossHired":false,"supplierName":"Karoo Fresh Holdings Ltd"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"depositHeld":1.0,"total":10005.0,"billing":"text","invoices":[{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","kind":"invoice","from":"2026-09-01","to":"2026-09-30","status":"sent","total":10005.0,"amountDue":10005.0}]},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"POST","path":"/api/rental/contracts","summary":"Book a hire. The units are reserved for outDate..dueBack; a booking that would double-book an item or overdraw a pool answers 409 naming the contract in the way.","auth":"jwt","body":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outDate":"2026-10-05","dueBack":"2026-10-13","site":"Erf 112, Midrand","lines":[{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":40}],"delivery":true,"collection":true,"notes":"Gate code 4411","billing":"on_return"},"responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"PATCH","path":"/api/rental/contracts/{id}","summary":"Change the site, notes or due date. A later due date is checked against the calendar like a booking.","auth":"jwt","body":{"dueBack":"2026-10-20","site":"12 Main Road, Germiston","notes":"Gate code 4411","billing":"monthly_arrears"},"responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"DELETE","path":"/api/rental/contracts/{id}","summary":"Delete a booking nothing has gone out on and that holds no deposit.","auth":"jwt","responseKind":"none","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/dispatch","summary":"Send units out on a date — every unit still to go, or the lines named. Booked units move to on hire.","auth":"jwt","body":{"on":"2026-10-05","lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":1}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"total":10005.0},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/off-hire","summary":"Off-hire on a date: the charge stops that day, whatever day it is collected. Units never sent are released.","auth":"jwt","body":{"on":"2026-10-13","lineIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"total":10005.0},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/return","summary":"The return inspection: per line, units back and missing, and cleaning and damage charges. A missing unit is charged at the item's replacement value. More than is with the customer is refused.","auth":"jwt","body":{"on":"2026-10-15","lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","back":38,"missing":2,"cleaning":350.0}]},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"total":10005.0},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/cancel","summary":"Cancel a booking nothing has gone out on; its units are released.","auth":"jwt","responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/invoice","summary":"Invoice what is left of an off-hired hire: the days no invoice has charged and the inspection's charges, or a credit note for days a month billed in advance did not use. Needs invoices:create too.","auth":"jwt","responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/cross-hire","summary":"Hire units in from another hire company to fill the booking: charged to the customer at the item's own rates, never on the register's counts. Off-hiring the line off-hires the supplier the same day and raises the supplier's bill.","auth":"jwt","body":{"hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":1,"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierDay":300.0,"supplierWeek":900.0,"supplierReference":"GPH-7781"},"responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"GET","path":"/api/rental/cross-hires","summary":"Every cross-hire with the customer's charge beside the supplier's bill (as it posted to Hire-in Costs) and the margin.","auth":"jwt","responseExample":[{"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","itemName":"Karoo Fresh Holdings Ltd","quantity":3,"supplierName":"Karoo Fresh Holdings Ltd","customerName":"Karoo Fresh Holdings Ltd","offHiredOn":"2026-09-01","customerCharge":1.0,"supplierCost":10005.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","margin":1.0}],"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"POST","path":"/api/rental/contracts/{id}/photos?movementId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&caption=Dent%20on%20the%20base%20plate","summary":"A photograph from the return inspection, as raw image bytes; recompressed by the server. ?movementId= ties it to a return.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","site":"text","status":"sent","outDate":"2026-09-01","dueBack":"text","offHiredOn":"2026-09-01","offHireRequestedBy":"text","offHireRequestedAt":"2026-09-01T09:15:00Z","delivery":false,"collection":false,"notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireItemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","kind":"standard","quantity":3,"qtyOut":3,"qtyBack":3,"qtyMissing":3,"withCustomer":1,"toGo":1,"offHiredOn":"2026-09-01","hireCharge":1.0,"periods":"2026-09","meterUnit":"each","meterOut":1.0,"crossHired":false,"supplierName":"Karoo Fresh Holdings Ltd"}],"charges":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","description":"Consulting services — August 2026","quantity":1,"unitAmount":10005.0,"total":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","stopType":"standard","status":"sent","hasProof":false}],"photoCount":3,"depositHeld":1.0,"total":10005.0,"billing":"text","invoices":[{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","kind":"invoice","from":"2026-09-01","to":"2026-09-30","status":"sent","total":10005.0,"amountDue":10005.0}]},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"GET","path":"/api/rental/contracts/{id}/deposit","summary":"The contract's deposit: what is held (taken less applied less refunded), every movement, and its pay links.","auth":"jwt","responseExample":{"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","held":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awaitingPayout":false}],"links":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","gateway":"payfast","amount":10005.0,"status":"sent","paidAt":"2026-09-01T09:15:00Z"}]},"module":"rental","addon":"Rental & Hire","scope":"rental:read"},{"method":"POST","path":"/api/rental/contracts/{id}/deposit","summary":"Take a refundable deposit at the counter into a bank account: DR bank / CR 2156, no VAT.","auth":"jwt","body":{"amount":5000.0,"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","on":"2026-10-05","method":"card","reference":"Card slip 0042"},"responseKind":"json","module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/deposit/link","summary":"Ask the hirer to pay the deposit online through the business's own Yoco or PayFast account; returns the page they open.","auth":"jwt","body":{"gateway":"yoco","amount":5000.0},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","gateway":"payfast","amount":10005.0,"status":"sent","paidAt":"2026-09-01T09:15:00Z"},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/deposit/link/{linkId}/cancel","summary":"Withdraw an unpaid deposit link so it takes nothing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","gateway":"payfast","amount":10005.0,"status":"sent","paidAt":"2026-09-01T09:15:00Z"},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/deposit/apply","summary":"Apply what is held to the hirer's invoice as a payment, up to what it owes. Needs invoices:edit too.","auth":"jwt","body":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","on":"2026-10-15"},"responseExample":{"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","held":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awaitingPayout":false}],"links":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","gateway":"payfast","amount":10005.0,"status":"sent","paidAt":"2026-09-01T09:15:00Z"}]},"module":"rental","addon":"Rental & Hire","scope":"rental:write"},{"method":"POST","path":"/api/rental/contracts/{id}/deposit/refund","summary":"Refund what is held, all of it or the amount named, from a bank account.","auth":"jwt","body":{"bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","on":"2026-10-15","amount":500.0,"reference":"EFT refund"},"responseExample":{"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","held":1.0,"movements":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"standard","amount":10005.0,"on":"2026-09-01","method":"eft","reference":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awaitingPayout":false}],"links":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","url":"https://app.ledgrsa.com/pay/3f1a7c92","gateway":"payfast","amount":10005.0,"status":"sent","paidAt":"2026-09-01T09:15:00Z"}]},"module":"rental","addon":"Rental & Hire","scope":"rental:write"}]},{"name":"Bills of materials","blurb":"The deep BOM work — multi-level explosion, low-level coding, where-used, make/buy and the cost roll-up — plus AUTHORING since 2026-08-24. /api/inventory/boms stays exactly as it was on the `inventory` module at Business tier: no existing tenant loses what it already has, and the two doors share one server implementation so neither can become the lenient one. Building is NOT here — it consumes components at batch cost and posts to the ledger, so it stays on `inventory:create`. There is an engineering-change step: a recipe is authored as a draft, submitted, and put into force by somebody holding `bom:approve` — which is what a build and MRP read.","endpoints":[{"method":"GET","path":"/api/bom/overview?q=cape&offset=0&awaitingDecision=true","summary":"The structural health of the BOM graph. Leads on what BLOCKS planning — parts flagged make-in-house with no recipe, and cycles — rather than on counts.","auth":"jwt","responseExample":{"bomCount":3,"activeBomCount":3,"makeItemCount":3,"buyItemCount":3,"phantomItemCount":3,"unplannedItemCount":3,"maxLevel":1,"cycleCount":3,"missingBomCount":3,"boms":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productSku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":false,"outputQty":3.0,"lineCount":3,"lowLevelCode":1,"estimatedUnitCost":2900.0,"hasSubAssemblies":false}],"bomTotal":42,"pendingCount":3,"cycles":[["text"]],"missingBoms":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qty":3.0,"sourceType":"invoice","onHand":1.0,"shortfall":1.0,"unitCost":2900.0,"extendedCost":10005.0,"leadTimeDays":30,"supplierName":"Karoo Fresh Holdings Ltd"}]},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{productId}/explode?qty=100&bomId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&wholeRuns=true&basis=standard","summary":"Multi-level explosion for a quantity, level by level. `basis` chooses what each bought-in part is valued at (planning, catalogue, on-hand, standard) and each line reports the basis that actually priced it; `override=<product id>:<price>`, repeated, is a session-only what-if that is never saved.","auth":"jwt","responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"nodes":[{"componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","parentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","level":1,"qtyPerTopUnit":1.0,"totalQty":3.0,"sourceType":"invoice","viaBomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentBomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","scrapPercent":15.0,"leadTimeOffsetDays":30,"isPhantom":false,"lowLevelCode":1,"leadTimeDays":30,"onHand":1.0,"unitCost":2900.0,"extendedCost":10005.0}],"requirements":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qty":3.0,"sourceType":"invoice","onHand":1.0,"shortfall":1.0,"unitCost":2900.0,"extendedCost":10005.0,"leadTimeDays":30,"supplierName":"Karoo Fresh Holdings Ltd"}],"maxDepth":1,"purchasedLineCount":3,"manufacturedLineCount":3,"missingBoms":["text"],"cycles":[["text"]],"rollup":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","materialCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"unitCost":2900.0,"currentCostPrice":10005.0,"variance":1.0,"missingBoms":["text"]}},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{productId}/where-used","summary":"Every parent this part appears in, at any level.","auth":"jwt","responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","parents":[{"parentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentSku":"LEN-TP-14G4","parentName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","qtyPer":1.0,"scrapPercent":15.0,"outputQty":3.0,"lowLevelCode":1}],"ancestors":[{"parentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentSku":"LEN-TP-14G4","parentName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","level":1,"qtyPer":1.0,"scrapPercent":15.0,"outputQty":3.0,"lowLevelCode":1,"qtyPerAncestorUnit":1.0,"via":["text"],"isTopLevel":false,"truncated":false}],"truncated":false},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{bomId}/detail","summary":"`kind` says whether this is something you make or a pack you sell. One BOM with its lines, effectivity and scrap factors, and what else a run of it makes. `outputs` is a recipe's co-products and by-products and is empty for a recipe that makes one thing; each carries `allocatedUnitCost`, what it would come in at on a run of the recipe as it now stands — computed from the price list and the recipe's own costs, never stored, so it cannot go stale. `primaryUnitCost` is what the finished good itself comes in at once the run's cost has been divided, and `byProductCredit` is what the by-products take off the run before the co-products share what is left.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productSku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","isDefault":false,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qtyPer":1.0,"scrapPercent":15.0,"effectiveQtyPer":1.0,"sourceType":"invoice","sourceOverride":"text","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","sortOrder":1,"notes":"Budget deferred to the next financial year.","unitCost":2900.0,"extendedCost":10005.0,"hasSubBom":false}],"lowLevelCode":1,"estimatedUnitCost":2900.0},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/planning/buffer-suggestion?serviceLevel=95&productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&abcClass=A","summary":"The safety stock and reorder point an item's sales swing and lead time call for, beside what it has: demand over the lead time from its monthly sales (invoices less credit notes), safety stock = z × the swing over the lead time at the service level (90, 95 or 98 %, default 95), both rounded up to how the item is counted. Give productId for one item, or abcClass for every item planned in that class. An item with under six months of sales or no lead time carries a blocker instead. Writes nothing.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Wall bracket 300mm","sku":"KSW-RM-BRKT300","qtyPrecision":0,"abcClass":"A","leadTimeDays":61,"currentSafetyStock":0.0,"currentReorderPoint":null,"historyMonths":8,"blocker":null,"serviceLevel":95,"monthlyMean":10.0,"monthlySwing":2.13809,"leadTimeDemand":20.04,"safetyStock":5.0,"reorderPoint":26.0}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"POST","path":"/api/bom/planning/buffer-suggestion/apply","summary":"Set these items' safety stock to what their sales call for at the service level, worked out again on the server. Items with no suggestion are left as they are; returns the items changed. The reorder point (Inventory's low-stock alert) is not written.","auth":"jwt","body":{"productIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"serviceLevel":95},"responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Wall bracket 300mm","sku":"KSW-RM-BRKT300","qtyPrecision":0,"abcClass":"A","leadTimeDays":61,"currentSafetyStock":0.0,"currentReorderPoint":null,"historyMonths":8,"blocker":null,"serviceLevel":95,"monthlyMean":10.0,"monthlySwing":2.13809,"leadTimeDemand":20.04,"safetyStock":5.0,"reorderPoint":26.0}],"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/planning?source=make&q=cape","summary":"Per-item planning parameters — make or buy, lead time, lot sizing, safety stock.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","sourceType":"invoice","leadTimeDays":30,"safetyStock":1.0,"lotSizing":"text","fixedOrderQty":3.0,"minOrderQty":3.0,"orderMultiple":1.0,"maxOrderQty":3.0,"maxStockLevel":1.0,"periodsOfSupply":1,"preferredSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","preferredSupplierName":"Karoo Fresh Holdings Ltd","planningCost":10005.0,"abcClass":"text","mrpActive":true,"notes":"Budget deferred to the next financial year.","lowLevelCode":1,"configured":false,"onHand":1.0,"hasBom":false}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"PUT","path":"/api/bom/planning","summary":"Set planning parameters for a product.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","sourceType":"invoice","leadTimeDays":30,"safetyStock":1.0,"lotSizing":"text","fixedOrderQty":3.0,"minOrderQty":3.0,"orderMultiple":1.0,"maxOrderQty":3.0,"maxStockLevel":1.0,"periodsOfSupply":1,"preferredSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","preferredSupplierName":"Karoo Fresh Holdings Ltd","planningCost":10005.0,"abcClass":"text","mrpActive":true,"notes":"Budget deferred to the next financial year.","lowLevelCode":1,"configured":true,"onHand":1.0,"hasBom":false},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceType":"make","leadTimeDays":5,"safetyStock":20.0,"lotSizing":"lot_for_lot","fixedOrderQty":3.0,"minOrderQty":3.0,"orderMultiple":1.0,"maxOrderQty":3.0,"maxStockLevel":1.0,"periodsOfSupply":1,"preferredSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","planningCost":10005.0,"abcClass":"A","mrpActive":true,"notes":"Budget deferred to the next financial year.","reorderPoint":1.0,"leadTimeBasis":"working"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"PUT","path":"/api/bom/{bomId}/planning","summary":"Set planning parameters that belong to one BOM rather than the item.","auth":"jwt","responseExample":{"status":"updated"},"body":{"isDefault":true,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"PUT","path":"/api/bom/lines/{lineId}/planning","summary":"Set a line's scrap factor and effectivity dates.","auth":"jwt","responseExample":{"status":"updated"},"body":{"sourceOverride":"make","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","operationSeq":1},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/planning/bulk-source","summary":"Flag many items make or buy at once.","auth":"jwt","body":{"productIds":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03,8c2d4e61-0a7f-4b93-b5e2-71d9c3a8f420","sourceType":"buy"},"responseExample":{"status":"updated","count":3},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/products/{productId}/variants","summary":"A product's variants, for the recipe editor's variant pickers. Under bom:view for the same reason /api/bom/products exists: a role holding only `bom:*` cannot call Inventory, and a picker that 403s looks exactly like a product with no variants. An empty list is the answer for a product that does not come in variants, and the editor draws no chooser for it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"CHR-DIN-OAK","name":"Oak"}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/products?q=cape","summary":"The products this tenant can name in a recipe — id, SKU, name and whether stock is tracked. Exists because a role holding only `bom:*` cannot call /api/inventory/products, so without it the recipe editor has no way to name a finished good or a component.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","isTracked":true}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{bomId}","summary":"One recipe in the shape the EDITOR saves — every field plus the component lines. Distinct from {bomId}/detail, which is the analysis shape (roll-up, tree, where-used): a dialog that saves what it loaded has to load what it saves.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"POST","path":"/api/bom","summary":"Author a recipe. Gated on `bom:create`, over the same implementation /api/inventory/boms uses — so a BOM engineer authors recipes without `inventory:create`, which also carries product creation and stock adjustments. Refuses a finished good that is not stock-tracked, a component that is the finished good, scrap at 100%, and an effectivity window that closes before it opens. `outputs` declares what else a run makes — a co-product shares the run's cost, a by-product is credited at what it fetches; omit the field to leave a recipe's outputs alone and send an empty list to clear them. `kind` is `recipe` (the default, and what every recipe in every tenant is) or `kit`: a pack sold as ONE invoice line whose components leave the shelf when the document posts and whose cost of sales is what those components actually cost. A kit is never built and its parent product must not be stock-tracked.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","kind":"co","qtyPerRun":1.0,"unitValue":10005.0,"sharePercent":15.0,"sortOrder":1,"notes":"Budget deferred to the next financial year."}],"kind":"standard","name":"Standard build","version":"1","outputQty":1.0,"labourCost":250.0,"overheadCost":80.0,"status":"active","notes":"Two people, one shift","effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":4.0,"scrapPercent":2.5,"notes":"Cut to length","sortOrder":0,"sourceOverride":"make","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","operationSeq":1}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/{bomId}/copy","summary":"The same recipe again, as a DRAFT — onto the same product (the next free version) or onto another one, carrying every line with its own scrap, note, make/buy override, day offset, date window and position. Copying is the road to a revision: without it an engineering change means retyping every line or editing the recipe the factory is building from, which is refused to an author. Every field is optional and the server fills in what the body does not say, from the same rule the dialog suggests with. `bom:create`, because a copy is a new recipe — and a copy is never the default.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"body":{"targetProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","targetVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","version":"2","name":"Karoo Fresh Holdings Ltd"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/replace-component","summary":"Swap one component for another across every recipe that uses it, or keep the part and change how much of it each recipe takes. A draft changes in place; a recipe IN FORCE gets a new draft copy for an approver rather than being changed under the factory; an archived one is left alone with its reason. `preview: true` writes nothing and answers the same list the apply acts on, so a dialog cannot show one thing and do another. An empty `bomIds` means every recipe that uses the part. `bom:edit`, plus `bom:create` when a recipe in force is in scope.","auth":"jwt","responseExample":{"preview":false,"edited":2,"drafted":1,"refused":1,"rows":[{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Standard build","version":"1","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","status":"active","outcome":"NEW_DRAFT","reason":null,"lines":2,"newBomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"body":{"oldProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","newProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyFactor":2.0,"bomIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"preview":false},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/export?status=active","summary":"Every recipe as a CSV, one row per component line, with the recipe's own fields repeated on each. The column shape is the one the import reads, so export → edit in a spreadsheet → import round-trips. Archived recipes are included — they are the record of how units already built were costed — and `?status=` narrows it. A recipe with no components still exports, as one row with the component columns empty, so re-importing the file cannot silently lose it. Capped at 500 recipes — past that it REFUSES and says to narrow by status, because a file that stopped silently at 500 re-imports as one that simply omits the rest. `bom:export`.","auth":"jwt","responseKind":"csv","module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{bomId}/document?format=pdf&qty=1","summary":"The recipe as a sheet to print — `format=pdf` (the default) or `format=html`. Carries the structure indented level by level, the quantities, positions and line notes, the cost broken out, where the part is used, and the controlled-document facts an audit asks for: whose recipe it is, which version, which revision, who approved it and when, and the date it was printed. A draft and an archived recipe print too — a draft is checked on paper before anybody approves it, and an archived one is the record of how units already built were costed — and each says on the sheet that it is not in force. `bom:view`, not `bom:export`: everything on the sheet is what the screen already shows the same person.","auth":"jwt","responseKind":"pdf","module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/lines/{lineId}/alternates","summary":"The approved equivalents for one component — the parts that may stand in for it when it is short. Each carries how many of the alternate stand in for one of the primary and what the stores can actually draw of it, because \"there is an approved alternate\" and \"there is one you could fit today\" are different answers and only the second gets a job moving. Ordered the way the engine tries them: priority first, then the part's name. `bom:view`.","auth":"jwt","responseExample":{"alternates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","alternateProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qtyPer":1.0,"priority":1,"notes":"Budget deferred to the next financial year.","available":1.0}]},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"PUT","path":"/api/bom/lines/{lineId}/alternates","summary":"Replace a line's approved equivalents. Replacing rather than patching because the set is small, capped at 5 and read as a whole — a partial update of an ordered list is the shape that silently loses the ordering somebody just set. A part cannot be its own alternate and the same part cannot be listed twice, which would double the cover the engine thinks it has. Deliberately NOT a change of substance for approval: an alternate changes nothing about what the recipe says the product IS, and every job already released is unaffected until somebody chooses to substitute on it. `bom:edit`.","auth":"jwt","responseExample":{"alternates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","alternateProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qtyPer":1.0,"priority":1,"notes":"Budget deferred to the next financial year.","available":1.0}]},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/{bomId}/open-jobs","summary":"Open jobs still building to a superseded version of this recipe — what the offer after an approval counts. A job is listed when it has already pinned a standard and that pin is older than the recipe's last change, or points at a different version; a job that has pinned nothing is not listed, because its standard is fixed at its first issue or completion and it will read the recipe in force on its own. Every listed job carries whether it can be re-pinned and, when it cannot, the reason — a planner offered two of the three jobs on the floor needs to be told what is different about the third. `bom:view` and `mrp:view`.","auth":"jwt","responseExample":{"jobs":[{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","qtyPlanned":1.0,"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomVersion":"1","reloadable":false,"blocker":"text"}],"reloadable":1,"offer":"text"},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{bomId}/attachments","summary":"The documents filed against a recipe — the drawing, the weld specification, the work instruction, the safety sheet. Each carries a signed URL that expires; a file whose URL could not be signed comes back with a null `url` rather than failing the whole list. `bom:view`, the same gate the recipe itself takes: the drawing is the specification the parts list was written to.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"POST","path":"/api/bom/{bomId}/attachments?filename=drawing-rev-C.pdf&caption=Serial%20plate%20before%20fitting&contentType=application%2Fpdf","summary":"File a document against a recipe. Raw bytes with `?filename=` — not multipart and not base64, which inflates a 4 MB scan by a third on exactly the connection this product is designed for. `?caption=` is optional and `?contentType=` is a hint only: what is stored is the type the server chose from its closed list. At most 8 files on a recipe and 15 MB each; a photograph is recompressed, a PDF is stored exactly as it arrived. `bom:edit` — the recipe's approval state is deliberately not consulted, because a drawing is very often approved after the recipe is, and a shop that cannot file the current revision against the live recipe files it in email.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"DELETE","path":"/api/bom/{bomId}/attachments/{linkId}","summary":"Take a document off a recipe. Removes the LINK, never the bytes: the same drawing may be referenced from a job card or a sales document, and a recipe is not a place from which somebody should be able to shred the specification an invoice is defended with. Deleting the file itself is `DELETE /api/files/{id}`. `bom:edit`.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/import?preview=true","summary":"Recipes from a CSV, one row per component line. Rows group into recipes by the finished good and the VERSION, never by the recipe's name. `?preview=true` writes nothing and answers the same shape the apply does, including which of Ledgr's fields each of the file's columns was read as. An unknown SKU is refused and never created; a recipe that already exists is REPLACED through the same writer a hand edit uses, so approval applies unchanged. Imported recipes land as drafts where the approval step applies. `bom:create`.","auth":"jwt","contentType":"text/csv","bodyRaw":"Finished good SKU,Component SKU,Qty per run\nKSW-FG-GATE36,KSW-RM-TUBE40,4","responseExample":{"preview":false,"created":2,"replaced":1,"refused":1,"fileErrors":["Row 7: No quantity on this row"],"rows":[{"productSku":"KSW-FG-GATE36","productName":"Double driveway gate 3.6m","recipeName":"Standard build","version":"1","lines":4,"outcome":"create","reason":null}],"columns":{"Qty per run":"qtyPer"}},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/{bomId}/revisions/compare?fromRevision=2&toRevision=5","summary":"Any two revisions of a recipe side by side (BOM-07): the header facts that differ, every component line added, removed or changed with both sides (quantity, unit, scrap, the step it is used at) and the facts that moved, and what each revision rolls up to a unit at today's component costs. The two need not be neighbours. 400 for the same revision twice, 404 for a revision this recipe does not have. `bom:view`.","auth":"jwt","responseExample":{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","from":2,"to":5,"fromAt":"2026-09-17T14:02:00Z","toAt":"2026-09-30T10:00:00Z","fromUnitCost":28.0,"toUnitCost":81.0,"header":[],"lines":[{"partName":"Hinge","change":"added","changed":[],"after":{"qtyPer":2.0,"scrapPercent":0.0,"operationSeq":20}},{"partName":"Bolt","change":"changed","changed":["scrap"],"before":{"qtyPer":10.0,"scrapPercent":0.0},"after":{"qtyPer":10.0,"scrapPercent":5.0}}],"unchangedLines":0},"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"GET","path":"/api/bom/{bomId}/revisions","summary":"What this recipe said at each point in its life, newest first (bounded at 100). Each revision holds the whole recipe as it stood after that change, and `changes` is the difference from the revision before it, worked out at read time so the wording improves for revisions already stored. A recipe changed before this shipped has no history, which is not the same as nothing having happened to it. `bom:view`.","auth":"jwt","responseExample":[{"revisionNo":3,"kind":"approved","note":"Checked against the drawing.","changedByName":"Thandi Mokoena","changedAt":"2026-09-01T09:15:00Z","name":"Standard build","version":"2","status":"active","lineCount":4,"changes":["Status awaiting approval → in force"]}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"POST","path":"/api/bom/{bomId}/revisions/{revisionNo}/restore","summary":"Put an earlier revision back — as a new DRAFT, never over the recipe in force, because deciding that an old recipe is what the factory should build again is an approver's decision. The draft is raised through the same writer as a recipe typed by hand, so every rule applies to it, and its version is suggested the way a copy's is. `bom:view` to read the history and `bom:create` to make the draft.","auth":"jwt","body":{"version":"2 restored"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Standard build","version":"3","outputQty":1.0,"status":"draft","lineCount":4},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"PUT","path":"/api/bom/{bomId}","summary":"Edit a recipe. An empty `lines` list leaves the components alone; send a list to replace them. The finished good is NOT re-pointable — moving a recipe to another product would restate every build already costed against it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outputs":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","kind":"co","qtyPerRun":1.0,"unitValue":10005.0,"sharePercent":15.0,"sortOrder":1,"notes":"Budget deferred to the next financial year."}],"kind":"standard","name":"Standard build","version":"1","outputQty":1.0,"labourCost":250.0,"overheadCost":80.0,"status":"active","notes":"Two people, one shift","effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":4.0,"scrapPercent":2.5,"notes":"Cut to length","sortOrder":0,"sourceOverride":"make","leadTimeOffsetDays":30,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","positionRef":"INV-0001","unit":"each","operationSeq":1}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"DELETE","path":"/api/bom/{bomId}","summary":"Remove a recipe — or ARCHIVE it when it has been built from, because it is then the record of how those units were costed. Gated on `bom:delete`.","auth":"jwt","responseKind":"none","module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"GET","path":"/api/bom/pending","summary":"The approver's queue — every recipe awaiting a decision, oldest submission first. Gated on `bom:view`, not `bom:approve`: an author needs to see that their own submission is still sitting there, and hiding the queue from them is how people start asking in person.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"}],"module":"bom","plan":"Manufacturing","scope":"bom:read"},{"method":"POST","path":"/api/bom/{bomId}/submit","summary":"Ask for a decision. `bom:edit` — submitting is the author's act. Refuses a recipe with no components: there is nothing to approve about one, and a button that always 400s is how people learn to ignore a workflow.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/{bomId}/approve","summary":"Put a recipe into force. `bom:approve`. There is deliberately NO self-approval refusal — nothing in Ledgr has one, the control is which roles hold the permission, and a three-user tenant with one engineer would otherwise never activate a recipe. Both actors are recorded.","auth":"jwt","body":{"note":"Checked against drawing rev C"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"module":"bom","plan":"Manufacturing","scope":"bom:write"},{"method":"POST","path":"/api/bom/{bomId}/reject","summary":"Send a recipe back to draft with a reason. `bom:approve`, and the reason is REQUIRED — a rejection with no reason means the author resubmits the same recipe.","auth":"jwt","body":{"note":"The beam quantity is per pair, not per frame"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","productSku":"LEN-TP-14G4","variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","version":"1","outputQty":3.0,"labourCost":10005.0,"overheadCost":10005.0,"status":"sent","notes":"Budget deferred to the next financial year.","lineCount":3,"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentVariantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","componentName":"Karoo Fresh Holdings Ltd","componentSku":"LEN-TP-14G4","qtyPer":1.0,"scrapPercent":15.0,"notes":"Budget deferred to the next financial year.","sortOrder":1}],"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","submittedAt":"2026-09-01T09:15:00Z","submittedByName":"Thandi Mokoena","approvedAt":"2026-09-01T09:15:00Z","approvedByName":"Thandi Mokoena","decisionNote":"Budget deferred to the next financial year.","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena","createdAt":"2026-09-01T09:15:00Z"},"module":"bom","plan":"Manufacturing","scope":"bom:write"}]},{"name":"Material planning (MRP)","blurb":"Runs, planned orders, the time-phased grid and pegging. Material Planning PROPOSES work orders; Production owns them — there is deliberately no second Work Orders tab here.","endpoints":[{"method":"GET","path":"/api/mrp/runs","summary":"MRP runs and their outcomes.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","status":"sent","horizonStart":"2026-09-01","horizonEnd":"2026-09-30","bucketDays":30,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","includeSafetyStock":true,"includeOnOrder":true,"netOffPlannedOrders":true,"supersedesRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedOrderCount":3,"purchaseOrderCount":3,"productionOrderCount":3,"exceptionCount":3,"demandLineCount":3,"productCount":3,"maxLevel":1,"totalPlannedValue":10005.0,"unplannedDemandCount":3,"convertedCount":3,"durationMs":1,"errorText":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena","kind":"standard","whatIfDemandPercent":15,"whatIfProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","whatIfProductName":"Karoo Fresh Holdings Ltd","whatIfExtraLeadDays":30}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/runs","summary":"Run MRP across the planning horizon.","auth":"jwt","responseExample":{"run":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","status":"sent","horizonStart":"2026-09-01","horizonEnd":"2026-09-30","bucketDays":30,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","includeSafetyStock":true,"includeOnOrder":true,"netOffPlannedOrders":true,"supersedesRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedOrderCount":3,"purchaseOrderCount":3,"productionOrderCount":3,"exceptionCount":3,"demandLineCount":3,"productCount":3,"maxLevel":1,"totalPlannedValue":10005.0,"unplannedDemandCount":3,"convertedCount":3,"durationMs":1,"errorText":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena","kind":"standard","whatIfDemandPercent":15,"whatIfProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","whatIfProductName":"Karoo Fresh Holdings Ltd","whatIfExtraLeadDays":30},"plannedOrders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","engineKey":"text","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","orderType":"standard","lowLevelCode":1,"bucketIndex":1,"qtyNet":8700.0,"qtyOrdered":1.0,"requiredDate":"2026-09-01","releaseDate":"2026-09-01","leadTimeDays":30,"status":"sent","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","unitCost":2900.0,"estimatedCost":10005.0,"exceptions":["text"],"requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","pegging":[{"demandSource":"referral","demandRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","parentEngineKey":"text","parentProductName":"Karoo Fresh Holdings Ltd"}],"onHand":1.0,"notes":"Budget deferred to the next financial year."}],"projections":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","lowLevelCode":1,"sourceType":"invoice","safetyStock":1.0,"leadTimeDays":30,"openingOnHand":1.0,"cells":[{"bucketIndex":1,"bucketStart":"2026-09-01","bucketEnd":"2026-09-30","grossRequirement":1.0,"scheduledReceipts":1.0,"plannedReceipts":1.0,"projectedOnHand":1.0,"netRequirement":8700.0,"plannedReleases":1.0,"belowSafety":false}]}],"buckets":[{"index":1,"start":"2026-09-01","end":"2026-09-30","label":"Karoo Fresh Holdings Ltd"}],"unplannedDemand":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","sourceType":"invoice","sourceRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","bucketIndex":1,"unplanned":false}],"cycles":[["text"]],"capacity":[{"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","cells":[{"bucketIndex":1,"plannedHours":3.0,"floorHours":3.0,"availableHours":3.0}]}],"supplyActions":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","source":"referral","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","action":"created","currentDate":"2026-09-01","suggestedDate":"2026-09-01","qty":3.0,"suggestedQty":3.0,"qtyPrecision":3}],"outsideWork":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","step":"text","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"unitCost":2900.0,"estimatedCost":10005.0,"releaseDate":"2026-09-01","requiredDate":"2026-09-01","leadDays":30,"status":"sent","requisitionNumber":"INV-0001","qtyPrecision":3}]},"body":{"name":"Karoo Fresh Holdings Ltd","horizonStart":"2026-09-01","horizonEnd":"2026-09-30","bucketDays":7,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","includeSafetyStock":true,"includeOnOrder":true,"includeForecast":true,"includeReorderPoints":true,"netOffPlannedOrders":true,"includeDraftBoms":false,"productIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"fenceOneDays":14,"fenceTwoDays":180,"includeDraftQuotes":false,"simulation":false,"whatIfDemandPercent":100,"whatIfProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","whatIfExtraLeadDays":30},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/runs/latest","summary":"The most recent run, which is what the screen opens on.","auth":"jwt","responseExample":{"run":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","status":"sent","horizonStart":"2026-09-01","horizonEnd":"2026-09-30","bucketDays":30,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","includeSafetyStock":true,"includeOnOrder":true,"netOffPlannedOrders":true,"supersedesRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedOrderCount":3,"purchaseOrderCount":3,"productionOrderCount":3,"exceptionCount":3,"demandLineCount":3,"productCount":3,"maxLevel":1,"totalPlannedValue":10005.0,"unplannedDemandCount":3,"convertedCount":3,"durationMs":1,"errorText":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena","kind":"standard","whatIfDemandPercent":15,"whatIfProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","whatIfProductName":"Karoo Fresh Holdings Ltd","whatIfExtraLeadDays":30},"plannedOrders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","engineKey":"text","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","orderType":"standard","lowLevelCode":1,"bucketIndex":1,"qtyNet":8700.0,"qtyOrdered":1.0,"requiredDate":"2026-09-01","releaseDate":"2026-09-01","leadTimeDays":30,"status":"sent","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","unitCost":2900.0,"estimatedCost":10005.0,"exceptions":["text"],"requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","pegging":[{"demandSource":"referral","demandRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","parentEngineKey":"text","parentProductName":"Karoo Fresh Holdings Ltd"}],"onHand":1.0,"notes":"Budget deferred to the next financial year."}],"projections":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","lowLevelCode":1,"sourceType":"invoice","safetyStock":1.0,"leadTimeDays":30,"openingOnHand":1.0,"cells":[{"bucketIndex":1,"bucketStart":"2026-09-01","bucketEnd":"2026-09-30","grossRequirement":1.0,"scheduledReceipts":1.0,"plannedReceipts":1.0,"projectedOnHand":1.0,"netRequirement":8700.0,"plannedReleases":1.0,"belowSafety":false}]}],"buckets":[{"index":1,"start":"2026-09-01","end":"2026-09-30","label":"Karoo Fresh Holdings Ltd"}],"unplannedDemand":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","sourceType":"invoice","sourceRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","bucketIndex":1,"unplanned":false}],"cycles":[["text"]],"capacity":[{"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","cells":[{"bucketIndex":1,"plannedHours":3.0,"floorHours":3.0,"availableHours":3.0}]}],"supplyActions":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","source":"referral","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","action":"created","currentDate":"2026-09-01","suggestedDate":"2026-09-01","qty":3.0,"suggestedQty":3.0,"qtyPrecision":3}],"outsideWork":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","step":"text","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"unitCost":2900.0,"estimatedCost":10005.0,"releaseDate":"2026-09-01","requiredDate":"2026-09-01","leadDays":30,"status":"sent","requisitionNumber":"INV-0001","qtyPrecision":3}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/available-to-promise?productIds=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03,8d2e4b17-9c3a-4f60-b5d1-7e0a2c9f4b86&excludeDocumentId=5a714b17-9c3a-4f60-b5d1-7e0a2c9f4b86","summary":"What can still be promised per product, and from when: on hand plus firm receipts (sent purchase orders, jobs on the floor) less firm commitments (customer demand, parts owed to jobs). productIds is a comma-separated list of at most 100; excludeDocumentId leaves out the document being edited.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","onHand":1.0,"now":1.0,"later":[{"from":"2026-09-01","qty":3.0}],"overcommitted":true,"qtyPrecision":3}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/delivery-promise","summary":"When a quantity of a product can be delivered, and the one thing that decides it: stock and firm receipts first, else the recipe and each item's lead time over the shop calendar. productId and qty are required; excludeDocumentId leaves out the document being edited. No date is given for an item with no lead time on record.","auth":"jwt","responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"date":"2026-09-01","bindingName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year.","leadTimeDays":30,"basis":"invoice","qtyPrecision":3},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/runs/{id}","summary":"One run — its planned orders, exceptions and the time-phased grid.","auth":"jwt","responseExample":{"run":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"INV-0001","name":"Karoo Fresh Holdings Ltd","status":"sent","horizonStart":"2026-09-01","horizonEnd":"2026-09-30","bucketDays":30,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","includeSafetyStock":true,"includeOnOrder":true,"netOffPlannedOrders":true,"supersedesRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedOrderCount":3,"purchaseOrderCount":3,"productionOrderCount":3,"exceptionCount":3,"demandLineCount":3,"productCount":3,"maxLevel":1,"totalPlannedValue":10005.0,"unplannedDemandCount":3,"convertedCount":3,"durationMs":1,"errorText":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","createdByName":"Thandi Mokoena","kind":"standard","whatIfDemandPercent":15,"whatIfProductId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","whatIfProductName":"Karoo Fresh Holdings Ltd","whatIfExtraLeadDays":30},"plannedOrders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","engineKey":"text","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","orderType":"standard","lowLevelCode":1,"bucketIndex":1,"qtyNet":8700.0,"qtyOrdered":1.0,"requiredDate":"2026-09-01","releaseDate":"2026-09-01","leadTimeDays":30,"status":"sent","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","unitCost":2900.0,"estimatedCost":10005.0,"exceptions":["text"],"requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","pegging":[{"demandSource":"referral","demandRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","parentEngineKey":"text","parentProductName":"Karoo Fresh Holdings Ltd"}],"onHand":1.0,"notes":"Budget deferred to the next financial year."}],"projections":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","lowLevelCode":1,"sourceType":"invoice","safetyStock":1.0,"leadTimeDays":30,"openingOnHand":1.0,"cells":[{"bucketIndex":1,"bucketStart":"2026-09-01","bucketEnd":"2026-09-30","grossRequirement":1.0,"scheduledReceipts":1.0,"plannedReceipts":1.0,"projectedOnHand":1.0,"netRequirement":8700.0,"plannedReleases":1.0,"belowSafety":false}]}],"buckets":[{"index":1,"start":"2026-09-01","end":"2026-09-30","label":"Karoo Fresh Holdings Ltd"}],"unplannedDemand":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","sourceType":"invoice","sourceRef":"INV-0001","qty":3.0,"requiredDate":"2026-09-01","bucketIndex":1,"unplanned":false}],"cycles":[["text"]],"capacity":[{"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","cells":[{"bucketIndex":1,"plannedHours":3.0,"floorHours":3.0,"availableHours":3.0}]}],"supplyActions":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","source":"referral","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","action":"created","currentDate":"2026-09-01","suggestedDate":"2026-09-01","qty":3.0,"suggestedQty":3.0,"qtyPrecision":3}],"outsideWork":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","sku":"LEN-TP-14G4","step":"text","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderNumber":"PO-0001","plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"unitCost":2900.0,"estimatedCost":10005.0,"releaseDate":"2026-09-01","requiredDate":"2026-09-01","leadDays":30,"status":"sent","requisitionNumber":"INV-0001","qtyPrecision":3}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/planned-orders/{id}/firm","summary":"Firm a recommendation so the next run stops moving it.","auth":"jwt","responseExample":{"status":"sent"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"PATCH","path":"/api/mrp/planned-orders/{id}","summary":"Change a recommendation's quantity, dates or supplier before converting it. The recommendation is pinned; the supplier's minimum, the pack multiple and whole runs are warned about, not refused.","auth":"jwt","responseExample":{"status":"sent","qtyOrdered":1.0,"requiredDate":"2026-09-01","releaseDate":"2026-09-01","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","estimatedCost":10005.0,"warnings":[]},"body":{"qtyOrdered":50.0,"requiredDate":"2026-10-20","releaseDate":"2026-10-13","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/planned-orders/{id}/cancel","summary":"Discard a recommendation.","auth":"jwt","responseExample":{"status":"sent"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/runs/{id}/production-schedule","summary":"The production schedule of a run: each finished item the shop makes to stock (made, at the top of its recipes), week by week over the run's buckets — forecast, firm demand, what the plan nets, receipts already on the way, the build (recommendations, pins and schedule lines) and whether the planner set it. `editable` is true only for the newest live plan.","auth":"jwt","responseExample":{"runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"MRP-0031","editable":true,"notEditableReason":null,"today":"2026-09-26","buckets":[{"index":0,"start":"2026-09-26","end":"2026-10-02","label":"26 Sep"}],"rows":[{"productId":"8c1e2f40-9d3a-4b7e-a1c2-5f6e7d8c9b0a","sku":"KSW-FG-GATE36","productName":"Double driveway gate 3.6m","qtyPrecision":0,"opening":4.0,"weeks":[{"bucketIndex":0,"start":"2026-09-26","forecast":6.0,"firm":2.0,"demand":6.0,"receipts":0.0,"build":10.0,"scheduled":true}]}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/production-schedule","summary":"Set a week's build on the current plan: every open plan line building that item that week is cancelled and one firm schedule line of the quantity takes its place (0 leaves none). The next run nets it as supply and buys or makes its parts. A what-if or a replaced plan is refused (409); a part rather than a finished made item is refused (400). Answers with the schedule as it now stands.","auth":"jwt","body":{"runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"8c1e2f40-9d3a-4b7e-a1c2-5f6e7d8c9b0a","bucketIndex":4,"qty":50.0},"responseExample":{"runId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","runNumber":"MRP-0031","editable":true,"notEditableReason":null,"today":"2026-09-26","buckets":[{"index":0,"start":"2026-09-26","end":"2026-10-02","label":"26 Sep"}],"rows":[{"productId":"8c1e2f40-9d3a-4b7e-a1c2-5f6e7d8c9b0a","sku":"KSW-FG-GATE36","productName":"Double driveway gate 3.6m","qtyPrecision":0,"opening":4.0,"weeks":[{"bucketIndex":0,"start":"2026-09-26","forecast":6.0,"firm":2.0,"demand":6.0,"receipts":0.0,"build":10.0,"scheduled":true}]}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/outside-work/convert","summary":"Put outside work (the purchase a subcontracted step of a job needs) onto requisitions, one per subcontractor. Each line is a service with no item, named for the step, the item and the job; ordered and received, it bills to 5067 and books the step it was for. A row whose route names no subcontractor is skipped with the reason. Needs mrp:create and procurement:create; a what-if's outside work is refused (409).","auth":"jwt","body":{"outsideWorkIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"submitImmediately":false},"responseExample":{"requisitionIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"requisitionNumbers":["INV-0001"],"workOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"workOrderNumbers":["PO-0001"],"convertedCount":3,"skipped":[{"plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/outside-work/{id}/cancel","summary":"Drop a piece of outside work from this plan. Only planned outside work can be dropped (409 otherwise, or on a what-if).","auth":"jwt","responseExample":{"status":"sent"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/supply-rules","summary":"Which locations are planned on their own and refilled from another, with the days on the road. A location with a rule is netted by itself (its stock, stock on the road to it, its located forecast, its reorder point); every other location is the main pool. Needs mrp:view.","auth":"jwt","responseExample":[{"id":"5d8e2a17-3c94-4b0f-8e61-a27f9c4d1b58","locationId":"8c2d4e61-0a7b-4f39-b5d2-91e6c3a8f7b4","locationName":"Durban branch","sourceLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceLocationName":"Johannesburg factory","leadDays":3}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/mrp/supply-rules","summary":"Refill a location from another, replacing that location's rule. Refused (400) when it would refill a location from itself, directly or round a loop, or with more than 365 days on the road. Answers the rules as they now stand. Needs mrp:edit.","auth":"jwt","body":{"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceLocationId":"8c2d4e61-0a7b-4f39-b5d2-91e6c3a8f7b4","leadDays":3},"responseExample":[{"id":"5d8e2a17-3c94-4b0f-8e61-a27f9c4d1b58","locationId":"8c2d4e61-0a7b-4f39-b5d2-91e6c3a8f7b4","locationName":"Durban branch","sourceLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sourceLocationName":"Johannesburg factory","leadDays":3}],"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/supply-rules/{locationId}","summary":"Stop refilling a location; it rejoins the main pool on the next run. 404 when it has no rule. Answers the rules as they now stand. Needs mrp:edit.","auth":"jwt","responseExample":[],"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/transfers/{id}/ship","summary":"Put a planned transfer on the road: an in-transit stock transfer from the source to the location it refills, refused (400) past what the source holds. Only a planned transfer ships (409 otherwise, or on a what-if). Needs mrp:create and inventory:create.","auth":"jwt","responseExample":{"id":"b41c7e09-6d2a-4f85-9e3b-0c58a1f7d264","productId":"e7a90c35-1b4d-4c62-a8f0-5d93b2e61c7a","productName":"Hex bolt M12 x 50","sku":"BOLT-M12-50","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationName":"Johannesburg factory","toLocationId":"8c2d4e61-0a7b-4f39-b5d2-91e6c3a8f7b4","toLocationName":"Durban branch","qty":30.0,"shipDate":"2026-10-16","arriveDate":"2026-10-19","neededDate":"2026-10-19","lateDays":0,"status":"shipped","stockTransferId":"9f2b6c41-7e08-4d3a-b1c5-68e4a02d9f17"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/transfers/{id}/cancel","summary":"Drop a planned transfer from this plan. Only a planned one can be dropped (409 otherwise, or on a what-if). Needs mrp:edit.","auth":"jwt","responseExample":{"id":"b41c7e09-6d2a-4f85-9e3b-0c58a1f7d264","productId":"e7a90c35-1b4d-4c62-a8f0-5d93b2e61c7a","productName":"Hex bolt M12 x 50","sku":"BOLT-M12-50","fromLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromLocationName":"Johannesburg factory","toLocationId":"8c2d4e61-0a7b-4f39-b5d2-91e6c3a8f7b4","toLocationName":"Durban branch","qty":30.0,"shipDate":"2026-10-16","arriveDate":"2026-10-19","neededDate":"2026-10-19","lateDays":0,"status":"cancelled"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/convert","summary":"Split recommendations into requisitions for the buy side and work orders for the make side.","auth":"jwt","responseExample":{"requisitionIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"requisitionNumbers":["INV-0001"],"workOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"workOrderNumbers":["PO-0001"],"convertedCount":3,"skipped":[{"plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}]},"body":{"plannedOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"groupBySupplier":true,"requisitionTitle":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","submitImmediately":false},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/replan-settings","summary":"Whether the morning replan orders what it plans (Material Planning → Order these each morning). Off by default.","auth":"jwt","responseExample":{"firmPlannedOrders":false},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/mrp/replan-settings","summary":"Turn the morning replan's ordering on or off. Needs mrp:create and procurement:create — it raises both work orders and purchase requests.","auth":"jwt","responseExample":{"firmPlannedOrders":true},"body":{"firmPlannedOrders":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/forecasts","summary":"Demand forecasts feeding the run.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-09-01","qty":3.0,"kind":"standard","consumedQty":3.0,"remainingQty":3.0,"notes":"Budget deferred to the next financial year.","method":"smoothed"}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/forecasts","summary":"Add a forecast.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","periodStart":"2026-10","qty":400.0,"kind":"forecast","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/forecast-suggestion?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&months=3","summary":"A forecast suggested from what an item sold: its monthly sales (invoices net of credit notes, from its first sale, at most 36 months, not the month in progress), the method that would have been closest on the latest months held back (3-month average, smoothed average, or same month last year), how many units a month it was out by, and a figure for each of the next `months` (1–12, default 3) from next month. Needs productId. With under six months of sales, `blocker` says why and nothing is suggested. Writes nothing.","auth":"jwt","responseExample":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Workshop trolley","sku":"KSW-FG-TROLLEY","qtyPrecision":0,"history":[{"month":"2026-06-01","qty":10.0},{"month":"2026-07-01","qty":6.0},{"month":"2026-08-01","qty":10.0}],"blocker":null,"method":"smoothed","methodLabel":"Smoothed average — recent months count for more","meanAbsoluteError":2.0,"months":[{"month":"2026-10-01","qty":9.0},{"month":"2026-11-01","qty":9.0},{"month":"2026-12-01","qty":9.0}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/forecast-suggestion/accept","summary":"Accept a suggestion: each month (perhaps edited) becomes an ordinary forecast line carrying the method, in one transaction. A month at zero adds nothing; this month or a past one is refused (400), as is an unknown method.","auth":"jwt","body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","method":"smoothed","months":[{"month":"2026-11-01","qty":12.0}]},"responseExample":{"ids":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/forecasts/{id}","summary":"Remove a forecast.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/capacity?siteId=5a714b17-9c3a-4f60-b5d1-7e0a2c9f4b86","summary":"Load against capacity per work centre across the horizon.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","lines":[{"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","availableHours":3.0,"plannedHours":3.0,"loadPercent":15.0,"overloadHours":3.0,"freeHours":3.0,"status":"sent","workingDays":30,"operationCount":3,"workOrderCount":3,"closedDays":[{"date":"2026-09-01","name":"Karoo Fresh Holdings Ltd","kind":"standard"}],"jobs":[{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","sequenceNo":1,"description":"Consulting services — August 2026","hours":3.0,"date":"2026-09-01","status":"sent"}]}],"totalAvailableHours":3.0,"totalPlannedHours":3.0,"overloadedCentreCount":3,"unassignedHours":3.0,"outsideWindowOperationCount":3},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/calendar","summary":"The manufacturing calendar — working days, shifts and shutdowns.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","publicHolidays":[{"date":"2026-09-01","name":"Karoo Fresh Holdings Ltd","isObserved":false}],"exceptions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","name":"Karoo Fresh Holdings Ltd","isWorking":false,"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","notes":"Budget deferred to the next financial year."}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/calendar","summary":"Add a calendar entry.","auth":"jwt","responseExample":{"status":"saved","days":"text"},"body":{"date":"2026-12-25","toDate":"2026-09-01","name":"Karoo Fresh Holdings Ltd","isWorking":false,"workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Public holiday"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/calendar?name=logo.png&workCentreId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Clear a range of calendar entries.","auth":"jwt","responseExample":{"status":"deleted","days":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/calendar/{id}","summary":"Remove one calendar entry.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/work-centres","summary":"Work centres, their capacity and their rates.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","capacityHoursPerDay":3.0,"machineCount":1,"efficiencyPercent":15.0,"workingDays":[30],"queueDays":30,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"isSubcontract":false,"observePublicHolidays":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","active":true,"notes":"Budget deferred to the next financial year.","dailyEffectiveHours":3.0,"routingOperationCount":3,"openOperationCount":3}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/work-centres","summary":"Add a work centre.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","capacityHoursPerDay":3.0,"machineCount":1,"efficiencyPercent":15.0,"workingDays":[30],"queueDays":30,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"isSubcontract":false,"observePublicHolidays":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","active":true,"notes":"Budget deferred to the next financial year.","dailyEffectiveHours":3.0,"routingOperationCount":3,"openOperationCount":3},"body":{"code":"WELD-01","name":"Welding bay 1","description":"Consulting services — August 2026","kind":"standard","capacityHoursPerDay":8.0,"machineCount":3,"efficiencyPercent":15.0,"workingDays":[30],"queueDays":30,"labourRatePerHour":420.0,"overheadRatePerHour":1.0,"isSubcontract":true,"observePublicHolidays":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","active":true,"notes":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"PUT","path":"/api/mrp/work-centres/{id}","summary":"Update a work centre.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","capacityHoursPerDay":3.0,"machineCount":1,"efficiencyPercent":15.0,"workingDays":[30],"queueDays":30,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"isSubcontract":false,"observePublicHolidays":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","active":true,"notes":"Budget deferred to the next financial year.","dailyEffectiveHours":3.0,"routingOperationCount":3,"openOperationCount":3},"body":{"code":"CT-001","name":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","kind":"standard","capacityHoursPerDay":16.0,"machineCount":3,"efficiencyPercent":15.0,"workingDays":[30],"queueDays":30,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"isSubcontract":true,"observePublicHolidays":true,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","active":true,"notes":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/work-centres/{id}","summary":"Remove a work centre.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/routings?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&qty=1","summary":"Routings — the ordered operations a part goes through.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year.","hoursForQty":3.0,"costForQty":3.0}],"qty":3.0,"startedQty":3.0,"setupHours":3.0,"runHours":3.0,"totalHours":3.0,"labourCost":10005.0,"overheadCost":10005.0,"subcontractCost":10005.0,"totalCost":10005.0,"costPerUnit":10005.0,"unassignedOperationCount":3}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/routings","summary":"Create a routing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year.","hoursForQty":3.0,"costForQty":3.0}],"qty":3.0,"startedQty":3.0,"setupHours":3.0,"runHours":3.0,"totalHours":3.0,"labourCost":10005.0,"overheadCost":10005.0,"subcontractCost":10005.0,"totalCost":10005.0,"costPerUnit":10005.0,"unassignedOperationCount":3},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Standard frame route","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":true,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year."}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/routings/{id}?qty=1","summary":"One routing and its operations.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year.","hoursForQty":3.0,"costForQty":3.0}],"qty":3.0,"startedQty":3.0,"setupHours":3.0,"runHours":3.0,"totalHours":3.0,"labourCost":10005.0,"overheadCost":10005.0,"subcontractCost":10005.0,"totalCost":10005.0,"costPerUnit":10005.0,"unassignedOperationCount":3},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/mrp/routings/{id}","summary":"Update a routing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year.","hoursForQty":3.0,"costForQty":3.0}],"qty":3.0,"startedQty":3.0,"setupHours":3.0,"runHours":3.0,"totalHours":3.0,"labourCost":10005.0,"overheadCost":10005.0,"subcontractCost":10005.0,"totalCost":10005.0,"costPerUnit":10005.0,"unassignedOperationCount":3},"body":{"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Standard frame route rev B","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/routings/{id}","summary":"Delete a routing.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/routings/{id}/operations","summary":"Add an operation to a routing.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","name":"Karoo Fresh Holdings Ltd","version":"1","status":"sent","isDefault":true,"expectedYieldPercent":15.0,"effectiveFrom":"2026-09-01","effectiveTo":"2026-09-30","notes":"Budget deferred to the next financial year.","operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year.","hoursForQty":3.0,"costForQty":3.0}],"qty":3.0,"startedQty":3.0,"setupHours":3.0,"runHours":3.0,"totalHours":3.0,"labourCost":10005.0,"overheadCost":10005.0,"subcontractCost":10005.0,"totalCost":10005.0,"costPerUnit":10005.0,"unassignedOperationCount":3},"body":{"sequenceNo":10,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","setupHours":0.5,"runHoursPerUnit":0.05,"isSubcontract":true,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"PUT","path":"/api/mrp/routings/operations/{opId}","summary":"Change an operation.","auth":"jwt","responseExample":{"status":"updated"},"body":{"sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","setupHours":3.0,"runHoursPerUnit":0.05,"isSubcontract":true,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractCostPerUnit":10005.0,"subcontractLeadDays":30,"instructions":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/routings/operations/{opId}","summary":"Remove an operation.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/routings/operations/{opId}/attachments","summary":"The files filed against a route step — the drawing, the jig set-up photograph, the weld procedure the operator works from. Each carries a signed URL that expires; a file whose URL could not be signed comes back with a null `url`. `mrp:view`, the gate the route itself takes.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/routings/operations/{opId}/attachments?filename=weld-procedure-rev-B.pdf&caption=Serial%20plate%20before%20fitting&contentType=application%2Fpdf","summary":"File a document against a route step. Raw bytes with `?filename=`, the same shape and limits as a recipe's files: at most 8 on a step and 15 MB each; a photograph is recompressed, a PDF is stored as it arrived. `?caption=` is optional and `?contentType=` a hint only. `mrp:edit`.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/routings/operations/{opId}/attachments/{linkId}","summary":"Take a file off a route step. Removes the LINK, never the bytes. `mrp:edit`.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/operations/{opId}/attachments","summary":"The files of the route step this order step was released from — what the operator opens at the machine. A step added to the order by hand has no route step and no files. `mrp:view`.","auth":"jwt","responseExample":{"attachments":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"SignedPO-4417.pdf","caption":"Serial plate before fitting","contentType":"application/pdf","sizeBytes":1,"url":"https://app.ledgrsa.com/pay/3f1a7c92","uploadedByName":"Karoo Fresh Holdings Ltd","createdAt":"2026-09-01T09:15:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/floor-queue?centreId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Operator mode's queue: every open step of a released or started order, highest priority first, with the planner's instructions, the files on its route step, the step it is waiting on and who is clocked on. `shopfloor:view` or `mrp:view`.","auth":"jwt","responseExample":{"items":[{"operationId":"7d2e1a00-1111-4222-8333-944455556666","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"WO-0042","productName":"Driveway gate","qty":4.0,"priority":2,"sequenceNo":10,"description":"Weld frame","workCentreId":"0b8e2f11-2222-4333-8444-555566667777","workCentreName":"Weld bay","status":"pending","plannedHours":6.0,"actualHours":0.0,"instructions":"Tack all four corners first.","attachmentCount":1,"scheduledStart":"2026-10-05T06:00:00Z","waitingOn":null,"runningTimers":[]}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/routings/operations/{opId}/checks","summary":"The quality checks a route step carries; release copies them onto each order's step. `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"9a1e0a00-1111-4222-8333-944455556666","label":"Gap between frame and hinge","kind":"measure","minValue":4.5,"maxValue":5.5,"unit":"mm","sequenceNo":10}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/routings/operations/{opId}/checks","summary":"Add a check to a route step: `kind` is pass_fail or measure; a measurement needs a lowest or highest acceptable value. Orders released from now on carry it. `mrp:edit`.","auth":"jwt","requestExample":{"label":"Gap between frame and hinge","kind":"measure","minValue":4.5,"maxValue":5.5,"unit":"mm"},"responseExample":{"items":[{"id":"9a1e0a00-1111-4222-8333-944455556666","label":"Gap between frame and hinge","kind":"measure","minValue":4.5,"maxValue":5.5,"unit":"mm","sequenceNo":10}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/routings/operations/{opId}/checks/{checkId}","summary":"Remove a route step's check. Orders already released keep theirs. `mrp:edit`.","auth":"jwt","responseExample":{"items":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/check-plans","summary":"The periodic quality checks this company keeps (T-M2.3): a check the clock raises every `everyHours`, not an order. `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"4a1e0a00-1111-4222-8333-944455556666","label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","everyHours":4,"workCentreId":null,"workCentreCode":null,"active":true}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/check-plans","summary":"Keep a periodic check (T-M2.3): `kind` pass_fail or measure, due every 1 to 168 hours on the plant's clock, optionally at one work centre. Its first slot is the one open now. `mrp:edit`.","auth":"jwt","requestExample":{"label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","everyHours":4,"active":true},"responseExample":{"id":"4a1e0a00-1111-4222-8333-944455556666","label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","everyHours":4,"workCentreId":null,"workCentreCode":null,"active":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"PUT","path":"/api/mrp/check-plans/{id}","summary":"Change a periodic check (T-M2.3); slots already raised keep what they were. `mrp:edit`.","auth":"jwt","requestExample":{"label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","everyHours":4,"active":true},"responseExample":{"id":"4a1e0a00-1111-4222-8333-944455556666","label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","everyHours":4,"workCentreId":null,"workCentreCode":null,"active":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/check-plans/{id}","summary":"Stop keeping a periodic check (T-M2.3); answers the plans still kept. Its log stays. `mrp:edit`.","auth":"jwt","responseExample":{"items":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/periodic-checks?days=7","summary":"The HACCP log (T-M2.3): every slot of the last `days` (1 to 92, default 7), newest first; `due` is what is open now and `missed` what passed unrecorded. Raises the open slot first, so it is current whether or not the hourly job has run. `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"5b2e0a00-1111-4222-8333-944455556666","planId":"4a1e0a00-1111-4222-8333-944455556666","label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","workCentreCode":null,"slotStart":"2026-10-12T06:00:00Z","dueBy":"2026-10-12T10:00:00Z","result":"pass","measuredValue":3.4,"notes":null,"recordedByName":"Thabo Nkosi","recordedAt":"2026-10-12T07:05:00Z","missed":false}],"due":0,"missed":0},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/periodic-checks/{id}/record","summary":"Record a slot of a periodic check (T-M2.3): `passed`, or `value` judged against the plan's limits. A slot already recorded is refused, not overwritten; a missed slot may be recorded late and stays marked missed. `mrp:edit`.","auth":"jwt","requestExample":{"value":3.4},"responseExample":{"id":"5b2e0a00-1111-4222-8333-944455556666","planId":"4a1e0a00-1111-4222-8333-944455556666","label":"Cold room temperature","kind":"measure","minValue":0.0,"maxValue":5.0,"unit":"C","workCentreCode":null,"slotStart":"2026-10-12T06:00:00Z","dueBy":"2026-10-12T10:00:00Z","result":"pass","measuredValue":3.4,"notes":null,"recordedByName":"Thabo Nkosi","recordedAt":"2026-10-12T07:05:00Z","missed":false},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/operations/{opId}/checks","summary":"An order step's checks and what was recorded against each. `shopfloor:view` or `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"8b2e0a00-1111-4222-8333-944455556666","operationId":"7d2e1a00-1111-4222-8333-944455556666","label":"Gap between frame and hinge","kind":"measure","minValue":4.5,"maxValue":5.5,"unit":"mm","result":"fail","measuredValue":5.9,"notes":null,"recordedByName":"Thabo Nkosi","recordedAt":"2026-09-28T08:14:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/operations/checks/{checkId}/record","summary":"Record a check: `passed` for pass or fail, `value` for a measurement judged against its limits. A failure puts the order on quality hold; a later pass does not lift it. Refused on a closed step. `shopfloor:edit` or `mrp:edit`.","auth":"jwt","requestExample":{"value":5.9},"responseExample":{"items":[{"id":"8b2e0a00-1111-4222-8333-944455556666","operationId":"7d2e1a00-1111-4222-8333-944455556666","label":"Gap between frame and hinge","kind":"measure","minValue":4.5,"maxValue":5.5,"unit":"mm","result":"fail","measuredValue":5.9,"notes":null,"recordedByName":"Thabo Nkosi","recordedAt":"2026-09-28T08:14:00Z"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/holds","summary":"Every quality hold an order has had, open first. While one is open nothing the order makes is received into stock. `shopfloor:view` or `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"6c3e0a00-1111-4222-8333-944455556666","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","operationId":"7d2e1a00-1111-4222-8333-944455556666","checkId":"8b2e0a00-1111-4222-8333-944455556666","reason":"Gap between frame and hinge: 5.9 mm","openedAt":"2026-09-28T08:14:00Z","openedByName":"Thabo Nkosi","disposition":null,"notes":null,"closedAt":null,"reworkOrderId":null}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/holds/{holdId}/resolve","summary":"Decide a quality hold: `disposition` release, rework or scrap; rework and scrap say what, in `notes`. Answers the order's progress, whose `holds` lists what is still undecided. `mrp:edit`.","auth":"jwt","requestExample":{"disposition":"rework","notes":"Two frames: re-weld the hinge side"},"responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text","holds":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/rework","summary":"Raise a rework order for units of a received lot. The order's one component is the item itself, issued from that lot by specific identification and received back on completion; its hours show as the rework's cost. `qty` may not exceed what the lot holds. Replay-safe on `clientId`. `mrp:create`.","auth":"jwt","requestExample":{"batchId":"4e5f0a00-1111-4222-8333-944455556666","qty":2,"reason":"Powder coat flaking on the hinge side","workCentreId":"0b8e2f11-2222-4333-8444-555566667777","clientId":"1a2b3c4d-1111-4222-8333-944455556666"},"responseExample":{"id":"1a2b3c4d-1111-4222-8333-944455556666","woNumber":"WO-0046"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/rework-step","summary":"Send units still in an open order to a rework step instead of booking them as scrap. The step is added at the named step's centre and rates; nothing is written off. `mrp:edit`.","auth":"jwt","requestExample":{"qty":2,"reason":"Weld porosity","fromOperationId":"7d2e1a00-1111-4222-8333-944455556666"},"responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text","holds":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/non-conformances","summary":"An order's non-conformances — cards on a Workflows board built from the Non-conformance template that name this order — with the boards one can be raised on, and whether this user may. `mrp:view`.","auth":"jwt","responseExample":{"boards":[{"id":"2d4e0a00-1111-4222-8333-944455556666","name":"Non-conformances"}],"items":[{"id":"3e5f0a00-1111-4222-8333-944455556666","itemKey":"NCR-0007","title":"Hinge gap out of tolerance","boardName":"Non-conformances","stage":"Raised","closed":false,"createdAt":"2026-09-28T08:20:00Z","lotNumber":"LOT-7"}],"mayRaise":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/{id}/non-conformances","summary":"Raise a non-conformance about this order, and optionally a hold or a lot of it: a card on the chosen Non-conformance board that names the order and lot. Needs `mrp:edit`, `workflows:create` and Workflows on the plan. Replay-safe on `clientId`.","auth":"jwt","requestExample":{"boardId":"2d4e0a00-1111-4222-8333-944455556666","title":"Hinge gap out of tolerance","description":"Two frames measured 5.9 mm.","holdId":"6c3e0a00-1111-4222-8333-944455556666","clientId":"5a6b0a00-1111-4222-8333-944455556666"},"responseExample":{"boards":[{"id":"2d4e0a00-1111-4222-8333-944455556666","name":"Non-conformances"}],"items":[{"id":"3e5f0a00-1111-4222-8333-944455556666","itemKey":"NCR-0007","title":"Hinge gap out of tolerance","boardName":"Non-conformances","stage":"Raised","closed":false,"createdAt":"2026-09-28T08:20:00Z","lotNumber":"LOT-7"}],"mayRaise":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/outside-work","summary":"Order an outsourced step's service from its subcontractor: the outside-work row Material Planning would plan, raised without a run, converted to a requisition (submitted for approval unless `submit` is false). The purchase order it becomes books the step on receipt, and the step's `subcontract` shows its price against the step's standard. `qty` defaults to what the step has left. `mrp:create` and `procurement:create`.","auth":"jwt","requestExample":{"qty":4,"submit":true},"responseExample":{"requisitionIds":["8f9e0a00-1111-4222-8333-944455556666"],"requisitionNumbers":["RQ-0012"],"convertedCount":1,"skipped":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/children","summary":"The sub-assembly orders an order has. `mrp:view`.","auth":"jwt","responseExample":{"raised":[],"children":[{"id":"9b8c0a00-1111-4222-8333-944455556666","woNumber":"WO-0051","productName":"Gate frame","qty":4.0,"status":"planned","plannedFinish":"2026-10-04"}],"skipped":[]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/{id}/subassemblies","summary":"Raise an order for each made component this order is short of, finishing the day before it starts. Each is a `subassembly` order whose parent is this one. A bought component, or one already on an open child order, is listed in `skipped` with why. `mrp:create`.","auth":"jwt","responseExample":{"raised":[{"id":"9b8c0a00-1111-4222-8333-944455556666","woNumber":"WO-0051","productName":"Gate frame","qty":4.0,"status":"planned","plannedFinish":"2026-10-04"}],"children":[{"id":"9b8c0a00-1111-4222-8333-944455556666","woNumber":"WO-0051","productName":"Gate frame","qty":4.0,"status":"planned","plannedFinish":"2026-10-04"}],"skipped":["Flat bar — bought, not made: Material Planning orders it"]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/serial-trace?serial=GT-2026-0042&productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"A serial's genealogy: the work order that made it and the serials built into it, level by level. `productId` chooses when two items share a number. `mrp:view`.","auth":"jwt","responseExample":{"root":{"serialNumber":"GT-2026-0042","productName":"Driveway gate","status":"in_stock","madeOnWorkOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","madeOnWoNumber":"WO-0042","builtFrom":[{"serialNumber":"MTR-88121","productName":"Gate motor","status":"consumed","madeOnWorkOrderId":null,"madeOnWoNumber":null,"builtFrom":[]}]}},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/work-centres/{id}/downtime?days=30","summary":"A centre's machine stops, newest first; an open stop has no `endedAt` and its hours run to now. `shopfloor:view` or `mrp:view`.","auth":"jwt","responseExample":{"items":[{"id":"5c1e0a00-1111-4222-8333-944455556666","workCentreId":"0b8e2f11-2222-4333-8444-555566667777","reason":"power","notes":"Stage 4","startedAt":"2026-09-28T08:00:00Z","endedAt":"2026-09-28T10:30:00Z","hours":2.5,"startedByName":"Thabo Nkosi"}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/work-centres/{id}/down","summary":"Mark a centre down. `reason` is breakdown, maintenance, changeover, power, no_material, no_operator or other. Refused while it is already down. Its lost hours come off the capacity table. `shopfloor:edit` or `mrp:edit`.","auth":"jwt","requestExample":{"reason":"breakdown","notes":"Wire feed jammed"},"responseExample":{"id":"5c1e0a00-1111-4222-8333-944455556666","workCentreId":"0b8e2f11-2222-4333-8444-555566667777","reason":"breakdown","notes":"Wire feed jammed","startedAt":"2026-09-28T08:00:00Z","endedAt":null,"hours":0.0,"startedByName":"Thabo Nkosi"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/work-centres/{id}/up","summary":"Mark a centre back up: its open stop ends now. Refused when it is not down. `shopfloor:edit` or `mrp:edit`.","auth":"jwt","responseExample":{"id":"5c1e0a00-1111-4222-8333-944455556666","workCentreId":"0b8e2f11-2222-4333-8444-555566667777","reason":"breakdown","notes":"Wire feed jammed","startedAt":"2026-09-28T08:00:00Z","endedAt":"2026-09-28T09:15:00Z","hours":1.25,"startedByName":"Thabo Nkosi"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/oee?days=30&siteId=5a714b17-9c3a-4f60-b5d1-7e0a2c9f4b86","summary":"OEE per centre over the last `days` days: availability (open hours less downtime), performance (standard hours earned over hours booked on closed steps, capped at 100% inside OEE) and quality (good over good plus scrapped). A factor with nothing to measure is null, and so is OEE. `mrp:view`.","auth":"jwt","responseExample":{"from":"2026-08-30","to":"2026-09-28","lines":[{"workCentreId":"0b8e2f11-2222-4333-8444-555566667777","code":"WELD","name":"Weld bay","openHours":168.0,"downtimeHours":12.5,"stops":3,"topReason":"power","availabilityPercent":92.6,"performancePercent":88.0,"qualityPercent":97.5,"oeePercent":79.4,"downSince":null}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/workers","summary":"The people a booking can name — the company's active users, each with the default rate Book labour starts from, or null. `mrp:view`.","auth":"jwt","responseExample":{"workers":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thabo Nkosi","labourRatePerHour":185.0}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/workers/performance?from=2026-09-01&to=2026-09-30","summary":"Hours per worker over a window (the last 30 days by default), and efficiency on the steps that closed: each closed step earns its planned hours, shared between the people who booked it in proportion to their hours on it. `efficiencyPercent` is null with no closed step to measure. `mrp:view`.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","workers":[{"workerId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thabo Nkosi","hours":42.5,"closedStepHours":38.0,"earnedHours":34.2,"efficiencyPercent":90.0,"stepCount":6}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/mrp/workers/{userId}","summary":"Set a worker's default labour rate, or clear it with `null`. Book labour starts from it; a step booking keeps the step's own frozen centre rate. `mrp:edit`.","body":{"labourRatePerHour":185.0},"auth":"jwt","responseExample":{"workers":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Thabo Nkosi","labourRatePerHour":185.0}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/scrap-reasons","summary":"The scrap reason list.","auth":"jwt","responseExample":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","controllable":true,"active":true,"isCustom":false,"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/scrap-reasons","summary":"Add a scrap reason.","auth":"jwt","responseExample":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","controllable":true,"active":true,"isCustom":false,"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"body":{"code":"weld-porosity","label":"Weld porosity","description":"Consulting services — August 2026","controllable":true,"active":true,"sortOrder":1},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/scrap-reasons/{code}","summary":"Remove a scrap reason.","auth":"jwt","responseExample":{"status":"deleted"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/scrap-analysis?from=2026-06-01&to=2026-08-31","summary":"Scrap by reason, by part and by work centre.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","totalQty":3.0,"totalCost":10005.0,"eventCount":3,"uncontrollableCost":10005.0,"loadSheddingCost":10005.0,"byReason":[{"key":"text","label":"Karoo Fresh Holdings Ltd","qty":3.0,"cost":10005.0,"eventCount":3,"controllable":true,"sharePercent":15.0}],"byWorkCentre":[{"key":"text","label":"Karoo Fresh Holdings Ltd","qty":3.0,"cost":10005.0,"eventCount":3,"controllable":true,"sharePercent":15.0}],"byProduct":[{"key":"text","label":"Karoo Fresh Holdings Ltd","qty":3.0,"cost":10005.0,"eventCount":3,"controllable":true,"sharePercent":15.0}],"byOperator":[{"key":"text","label":"Karoo Fresh Holdings Ltd","qty":3.0,"cost":10005.0,"eventCount":3,"controllable":true,"sharePercent":15.0}],"recent":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","operationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"operationDescription":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"reasonCode":"CT-001","reasonLabel":"Karoo Fresh Holdings Ltd","controllable":true,"operatorUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","operatorName":"Karoo Fresh Holdings Ltd","unitCost":2900.0,"totalCost":10005.0,"occurredAt":"2026-09-01T09:15:00Z","notes":"Budget deferred to the next financial year."}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/batch-trace?batchId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&direction=backward&batchNumber=B-2026-0412","summary":"Genealogy: forward from a supplier lot to every job and finished batch that consumed it, backward from a finished batch to every lot inside it.","auth":"jwt","responseExample":{"direction":"text","rootBatchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootBatchNumber":"INV-0001","rootProductName":"Karoo Fresh Holdings Ltd","rootSku":"LEN-TP-14G4","nodes":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"unitCost":2900.0,"supplier":"Karoo Fresh Holdings Ltd","expiryDate":"2026-09-01","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","workOrderStatus":"sent","consumedAt":"2026-09-01T09:15:00Z","depth":1,"kind":"standard"}],"maxDepth":1,"truncated":false,"unaccountedQty":3.0},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/mrp/work-orders/{id}/genealogy","summary":"The lots that went into one work order's output.","auth":"jwt","responseExample":{"direction":"text","rootBatchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootBatchNumber":"INV-0001","rootProductName":"Karoo Fresh Holdings Ltd","rootSku":"LEN-TP-14G4","nodes":[{"batchId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","batchNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","qty":3.0,"unitCost":2900.0,"supplier":"Karoo Fresh Holdings Ltd","expiryDate":"2026-09-01","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","workOrderStatus":"sent","consumedAt":"2026-09-01T09:15:00Z","depth":1,"kind":"standard"}],"maxDepth":1,"truncated":false,"unaccountedQty":3.0},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"}]},{"name":"Production & work orders","blurb":"The execution screen. A completion posts what the stock ledger RECEIVED, not what was requested — work order quantities are fractional and stock movements are integers, and posting qty × standard against round(qty) received was this product's whole inventory-to-ledger difference.","endpoints":[{"method":"GET","path":"/api/work-orders?status=released","summary":"Work orders. The status filter lives here and nowhere else — it is the only way to reach a cancelled or completed order.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","qtyPlanned":1.0,"qtyCompleted":1.0,"status":"sent","priority":1,"plannedStart":"2026-09-01","plannedFinish":"text","actualStart":"2026-09-01","actualFinish":"text","estimatedCost":10005.0,"actualCost":10005.0,"assemblyBuildId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mrpRunNumber":"INV-0001","notes":"Budget deferred to the next financial year.","shortages":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","required":1.0,"onHand":1.0,"short":1.0}],"canStart":true}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/page?q=gate&status=in_progress&page=1&limit=50","summary":"One page of work orders for the Production list: searched by order number, product, product code or the customer of an order made to order; open work first (priority, then due date), then closed work, latest first. Answers the page and how many match.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"WO-0042","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Driveway gate 3.6m","qtyPlanned":4.0,"qtyCompleted":1.0,"status":"in_progress","priority":2}],"total":53,"page":1,"limit":50,"totalPages":2},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/kpis?days=90","summary":"How the floor is doing over the last `days` (7 to 366, default 90) — how many orders finished and the share finished by their planned finish, units made against units planned, planned hours against booked hours on closed steps, the money in WIP by how long ago each job was released, and finished and on-time orders per week for twelve weeks. A percentage is null when there is nothing to measure it on. `mrp:view`.","auth":"jwt","responseExample":{"from":"2026-07-01","to":"2026-09-28","finished":31,"onTimePercent":83.9,"outputVsPlanPercent":97.2,"labourEfficiencyPercent":91.5,"wipAgeing":[{"label":"Under a week","jobs":4,"balance":18250.0}],"weeks":[{"weekStarting":"2026-09-21","finished":3,"onTime":2}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/counts","summary":"How many work orders are in each status — the figures behind Production's tiles, unaffected by the list's filter or search.","auth":"jwt","responseExample":{"planned":12,"released":7,"in_progress":3,"completed":30,"cancelled":1},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/late","summary":"How many open work orders are past the day they are needed (the required date, else the planned finish) — Production's late figure and the dashboard's.","auth":"jwt","responseExample":{"asOf":"2026-10-11","count":2},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders","summary":"Raise a work order.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","qtyToStart":"2026-09-01"},"body":{"variantId":"7d2e1a00-1111-4222-8333-944455556666","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":250.0,"bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedStart":"2026-09-01","plannedFinish":"2026-09-05","priority":5,"notes":"Budget deferred to the next financial year.","clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/make-to-order","summary":"Make one item of a live quote or invoice to order. The work order is linked to the document, due on its delivery date, and planning stops counting that quantity as unmet demand. 409 when the document is a draft, already made to order, or the item has no recipe.","auth":"jwt","body":{"variantId":"7d2e1a00-1111-4222-8333-944455556666","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"7b2e4d10-8c3f-4a5e-b9d1-6f0a2c4e8b17"},"responseExample":{"id":"9c4e1a27-3d5b-4f60-8e12-7a9b0c1d2e3f","woNumber":"WO-0042"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/make-to-order?documentId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The jobs making a quote or invoice to order, which of its items can be made (an active recipe), and why the document itself cannot be made to order, if it cannot.","auth":"jwt","responseExample":{"jobs":[{"productId":"7b2e4d10-8c3f-4a5e-b9d1-6f0a2c4e8b17","workOrderId":"9c4e1a27-3d5b-4f60-8e12-7a9b0c1d2e3f","woNumber":"WO-0042","status":"planned","qtyPlanned":5.0}],"makeableProductIds":["7b2e4d10-8c3f-4a5e-b9d1-6f0a2c4e8b17"],"refusal":null},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/make-to-order/waiting","summary":"The orders a customer has said yes to (an accepted quote, an open sales order, a draft invoice, a portal request) with an item made here and no open job making it — Material Planning's list for making to order. No money is on it.","auth":"jwt","responseExample":[{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"QUO-2026-006","documentType":"quote","status":"accepted","customerName":"Mthembu Farms","wantedBy":"2026-11-19","items":[{"productId":"7b2e4d10-8c3f-4a5e-b9d1-6f0a2c4e8b17","variantId":null,"description":"Driveway gate 4m","qty":2.0}]}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/{id}","summary":"One work order with its material, labour and cost position.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","locationName":"Karoo Fresh Holdings Ltd","qtyPlanned":1.0,"qtyCompleted":1.0,"status":"sent","priority":1,"plannedStart":"2026-09-01","plannedFinish":"text","actualStart":"2026-09-01","actualFinish":"text","estimatedCost":10005.0,"actualCost":10005.0,"assemblyBuildId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mrpRunNumber":"INV-0001","notes":"Budget deferred to the next financial year.","shortages":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","required":1.0,"onHand":1.0,"short":1.0}],"canStart":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/work-orders/{id}","summary":"Move an open work order: `plannedStart`, `plannedFinish`, `requiredDate` and `priority` (1 first, to 9). Each field left out is left alone. A released order's steps follow the new dates when they still carry the order's own dates; a step scheduled on its own keeps them. Refused on a completed or cancelled order, for a due date before the start, and for a date more than five years from today. `mrp:edit`.","body":{"plannedStart":"2026-10-05","plannedFinish":"2026-10-09","priority":2,"requiredDate":"2026-09-12"},"auth":"jwt","responseExample":{"status":"rescheduled","stepsMoved":"2"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/release","summary":"Release the order to the floor.","auth":"jwt","responseExample":{"status":"sent","operationsCreated":1},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/reload-recipe","summary":"Re-pin an open job to the recipe in force now. A job fixes its components once, on purpose — a standard is what actuals are measured against, and re-reading it at completion compares actual against actual and reports a zero variance for ever — so an approved engineering change otherwise reaches only jobs released after it, and every job already open keeps building to the superseded drawing. This is that decision taken deliberately, and only while taking it is free: it is REFUSED once material has been issued, time has been booked or a unit has been completed, because re-pinning then would restate the baseline those actuals were already measured against. The refusal names which of the three it was. Optional `bomId` names the version to pin — checked to belong to this job's product — and omitting it means whichever recipe is in force. The job's route is deliberately untouched. `mrp:edit`.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomVersion":"1","changed":false,"previousLines":1,"lines":1,"previousMaterialPerUnit":1.0,"materialPerUnit":1.0,"standardRepinned":false},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/cancel","summary":"Cancel an order and return what it holds.","auth":"jwt","responseExample":{"status":"sent","wipWrittenOff":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/complete","summary":"Complete the order. closeJob stays a wire name — the screen says \"work order\" everywhere, but renaming the field would break the contract.","auth":"jwt","responseExample":{"status":"sent","completionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyCompleted":1.0,"standardUnitCost":2900.0,"standardTotal":10005.0,"completionJournalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","varianceJournalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","wipBalance":10005.0,"isFinal":false,"totalVariance":10005.0,"variances":[{"type":"standard","label":"Karoo Fresh Holdings Ltd","amount":10005.0,"accountCode":"CT-001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","standardQty":3.0,"actualQty":3.0,"standardRate":15.0,"actualRate":15.0,"explanation":"text","favourable":false,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"backflushed":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qty":3.0,"actualUnitCost":2900.0,"actualTotalCost":10005.0,"standardUnitCost":2900.0,"short":false,"issueType":"standard","issuedAt":"2026-09-01T09:15:00Z","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"shortComponents":["text"],"incompleteOperations":["text"]},"body":{"lotNumber":"L26-0412","expiryDate":"2026-12-30","qtyCompleted":248.0,"qtyScrapped":2.0,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","notes":"Budget deferred to the next financial year.","backflush":true,"closeJob":true,"serials":[],"clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/completions/{id}/reverse","summary":"Reverse a completion. Withdraws the units actually moved, not the quantity requested — the reversal path carried the same rounding defect mirrored.","auth":"jwt","body":{"qty":2.0,"reason":"Booked against the wrong work order"},"responseExample":{"reversalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyReversed":1.0,"standardTotal":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","varianceJournalReversedId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobReopened":false,"wipBalance":10005.0},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/issuable?q=bracket","summary":"What can be issued to this job, or returned from it: its recipe items and everything it already holds, plus — with `q` — any stock item whose name or code matches. Each with what is on the shelf and what the job holds, which is the most a return may give back. `mrp:view`.","auth":"jwt","responseExample":{"items":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"FB-40x5","name":"Flat bar 40x5","unit":"m","onHand":120.0,"issued":20.0,"onRecipe":true}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/{id}/document?format=pdf","summary":"The work order on paper — `format=pdf` (the default) or `format=html`: the job and its dates, a QR code for the order, every step of its route with the operator's instructions, a QR code for the step and boxes to sign it off, and the pick list — needed, issued, still to pick. The codes are the ones the Production scanner reads. `mrp:view`.","auth":"jwt","responseKind":"pdf","module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/{id}/labels?format=pdf&completionId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&kind=case&count=24&copies=1","summary":"Labels for what the job made, 100 × 60 mm, one a page: one per completion with the product, its lot, the quantity, the date and a QR code the scanner reads as that lot — or, before anything is made, one for the order. `completionId` narrows to one completion. A product with a GTIN also gets a GS1-128 a retailer's dock scans, on an A6 label (T-M2.4): `kind=lot` (the default) carries (01) GTIN-14, (17) expiry and (10) lot; `kind=case&count=` adds (37) the count with (02); `kind=pallet&count=` adds a second symbol, (00) an SSCC from the company's GS1 prefix, new for every copy and never repeated. `copies=` 1–100 of each. A case or pallet label is refused (409) for a product with no GTIN, and a pallet label for a company with no prefix. `mrp:view`.","auth":"jwt","responseKind":"pdf","module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/{id}/issue","summary":"Issue material. With no lines, issues the recipe's requirement for the outstanding quantity, which is what a storeman picking a whole job wants. Negative quantities return material at the price the job was charged.","auth":"jwt","responseExample":{"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qty":3.0,"actualUnitCost":2900.0,"actualTotalCost":10005.0,"standardUnitCost":2900.0,"short":false,"issueType":"standard","issuedAt":"2026-09-01T09:15:00Z","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"totalCost":10005.0,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","wipBalance":10005.0,"shortComponents":["text"]},"body":{"allowAlternates":false,"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":3.0,"variantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"qtyForUnits":1.0,"locationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","notes":"Budget deferred to the next financial year.","serials":{},"clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/{id}/labour","summary":"Book hours against the order.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","labourCost":"text","overheadCost":"text","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","wipBalance":"text"},"body":{"hours":6.0,"rate":15.0,"overheadRate":15.0,"operationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","entryDate":"2026-09-01","notes":"Budget deferred to the next financial year.","clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/costing","summary":"The order's costing view — material, labour, overhead and the variances against standard.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","status":"sent","qtyPlanned":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"stdMaterialPerUnit":1.0,"stdLabourPerUnit":1.0,"stdOverheadPerUnit":1.0,"stdTotalPerUnit":10005.0,"stdHoursPerUnit":3.0,"stdLabourRate":15.0,"standardCostOfOutput":10005.0,"actualMaterial":1.0,"actualLabour":1.0,"actualOverhead":1.0,"actualTotal":10005.0,"actualHours":3.0,"wipRelieved":1.0,"wipVarianceCleared":1.0,"wipBalance":10005.0,"totalVariance":10005.0,"variances":[{"type":"standard","label":"Karoo Fresh Holdings Ltd","amount":10005.0,"accountCode":"CT-001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","standardQty":3.0,"actualQty":3.0,"standardRate":15.0,"actualRate":15.0,"explanation":"text","favourable":false,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"issues":[],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hours":3.0,"actualRate":15.0,"actualCost":10005.0,"standardRate":15.0,"overheadCost":10005.0,"entryType":"standard","entryDate":"2026-09-01","employeeName":"Thandi Mokoena","notes":"Budget deferred to the next financial year.","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"hasRouting":false,"standardPinned":false,"completions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyCompleted":1.0,"qtyScrapped":1.0,"standardUnitCost":2900.0,"standardTotal":10005.0,"isFinal":false,"completedAt":"2026-09-01T09:15:00Z","completedByName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","reversedAt":"2026-09-01T09:15:00Z","reversalOfId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reversalReason":"Budget deferred to the next financial year.","qtyStillInStock":1.0,"canReverse":false}]},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/work-orders/schedule?direction=backward&siteId=5a714b17-9c3a-4f60-b5d1-7e0a2c9f4b86","summary":"Every open work order laid onto the hours its work centres actually have, after each centre's queue days, forward from today in priority order — or, with `?direction=backward`, back from each job's due date so it starts as late as still finishes on time (a job with no due date, or one that cannot fit, is laid forward): each job's proposed start and finish, whether that changes its planned dates, how late it will be against the date it is needed by, and each operation's dates at its centre. A proposal — nothing is moved.","auth":"jwt","responseExample":{"today":"text","jobs":[{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","productName":"Karoo Fresh Holdings Ltd","status":"sent","priority":1,"plannedStart":"2026-09-01","plannedFinish":"text","scheduledStart":"2026-09-01","scheduledFinish":"text","requiredDate":"2026-09-01","daysLate":30,"cannotPlace":"text","changes":true}],"operations":[{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","operationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreName":"Karoo Fresh Holdings Ltd","hours":3.0,"start":"2026-09-01","finish":"text","subcontract":true}],"lateCount":3,"changeCount":3,"cannotPlaceCount":3},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/schedule/apply","summary":"Apply the reviewed schedule: every job it moves gets the proposed planned start and finish (the date it was needed by is kept), and a released job's operations their scheduled dates. The body lists the dates reviewed; when the schedule worked out now differs, nothing is written and 409 is returned.","auth":"jwt","responseExample":{"updatedJobs":1,"updatedOperations":1},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/operations","summary":"The order's operations and their state.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/{id}/operations","summary":"Attach operations to the order, usually copied from the routing.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"body":{"sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","setupHours":3.0,"runHoursPerUnit":3.0,"isSubcontract":false,"subcontractCostPerUnit":10005.0,"notes":"Budget deferred to the next financial year.","instructions":"Deburr both ends before the bend.","clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/start","summary":"Start an operation.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/book","summary":"Book time and quantity against an operation.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"body":{"hours":2.5,"qtyCompleted":60.0,"qtyScrapped":1.0,"scrapReasonCode":"CT-001","scrapNotes":"Budget deferred to the next financial year.","complete":true,"notes":"Budget deferred to the next financial year.","clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15","workerId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/operations/{opId}","summary":"The order a step belongs to, with its progress — what scanning a step's code on the traveller opens. `mrp:view`; another company's step is not found.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/operations/{opId}/subcontract-order","summary":"Order an outsourced step from its subcontractor: a draft purchase order for the units still to send. Receiving it books the step (DR 1315 / CR 5067) and the supplier's bill clears 5067.","auth":"jwt","body":{"supplierId":"bc1d8fe0-3c9e-5d4a-b109-3998299318d9","qty":10.0,"unitCost":90.0,"expectedDate":"2026-10-07"},"responseExample":{"orders":[{"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","status":"sent","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","operationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","step":"text","qtyOrdered":1.0,"qtyReceived":1.0,"unitCost":2900.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"referral"}],"note":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/work-centres/{id}/signals","summary":"A machine's own signals: running, stopped or fault, with the device's sequence number and the good and reject parts it counted. A stop that lasts the work centre's threshold (2 minutes unless set) becomes a downtime event with no reason yet, closed by the next running; a shorter one is a micro-stop. A sequence number already taken changes nothing. A key scoped to machine-signals:write may post only for the work centres it names and can read nothing. At most 500 signals a post.","auth":"jwt","body":{"signals":[{"seq":1042,"kind":"stopped","at":"2026-10-12T10:15:00+02:00","good":120,"reject":2}]},"responseKind":"json","module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/downtime/{eventId}/reason","summary":"Say why a machine stopped: the reason on a stop, typically one the machine recorded with no reason yet.","auth":"jwt","body":{"reason":"changeover","notes":"Die change for the next job"},"responseExample":{"reason":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/mrp/work-centres/{id}/maintenance","summary":"A machine's preventive maintenance plans: each with its hours run or units processed since the last service, whether it is due, and the job card booked for it.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","trigger":"hours","cycle":1.0,"cadence":"text","downtimeHours":3.0,"lastServiceAt":"2026-09-01T09:15:00Z","meter":1.0,"due":false,"nextDueOn":"2026-09-01","standing":"text","openJobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","openJobNumber":"JC-0001","openScheduledStart":"2026-09-01","active":true}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/mrp/work-centres/{id}/maintenance","summary":"A maintenance plan for the machine: a job card for whoever services it when the hours run (or units processed) since the last service reach the cycle, or on a calendar cadence. The card's scheduled hours come off the centre's capacity. Needs Job Cards on the plan.","auth":"jwt","body":{"contactId":"bc1d8fe0-3c9e-5d4a-b109-3998299318d9","title":"500-hour service","trigger":"hours","cycle":500.0,"cadence":"quarterly","downtimeHours":8.0,"lastServiceOn":"2026-10-01"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreName":"Karoo Fresh Holdings Ltd","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","trigger":"hours","cycle":1.0,"cadence":"text","downtimeHours":3.0,"lastServiceAt":"2026-09-01T09:15:00Z","meter":1.0,"due":false,"nextDueOn":"2026-09-01","standing":"text","openJobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","openJobNumber":"JC-0001","openScheduledStart":"2026-09-01","active":true},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"DELETE","path":"/api/mrp/maintenance-plans/{planId}","summary":"Stop planning a machine's service. Cards already raised stay.","auth":"jwt","responseKind":"none","module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/mrp/maintenance/check","summary":"Raise every due maintenance plan's job card now rather than at the overnight run. A plan with a card still open raises nothing.","auth":"jwt","responseExample":{"raised":["text"]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/operations/{opId}/free-issue","summary":"The material sent with an outsourced step, and where each part stands: sent, consumed by the subcontractor's returns, brought back, and still at their location. It stays the business's stock (1310) throughout.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","location":"text","sent":1.0,"consumed":1.0,"returned":1.0,"atSubcontractor":1.0,"perUnit":1.0}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/operations/{opId}/free-issue","summary":"Send material with an outsourced step: a confirmed transfer to the subcontractor's own stock location, which posts nothing. Their return then consumes the job's recipe share from that location into WIP.","auth":"jwt","body":{"lines":[{"productId":"bc1d8fe0-3c9e-5d4a-b109-3998299318d9","qty":100.0}]},"responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","location":"text","sent":1.0,"consumed":1.0,"returned":1.0,"atSubcontractor":1.0,"perUnit":1.0}],"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/free-issue/return","summary":"Bring back what is still at the subcontractor for the step: a transfer home that posts nothing. 409 when nothing is left there.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","location":"text","sent":1.0,"consumed":1.0,"returned":1.0,"atSubcontractor":1.0,"perUnit":1.0}],"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-orders/{id}/subcontract-orders","summary":"The purchase orders buying this work order's outsourced steps — raised on the step or from Material Planning.","auth":"jwt","responseExample":{"orders":[{"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","status":"sent","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","operationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","step":"text","qtyOrdered":1.0,"qtyReceived":1.0,"unitCost":2900.0,"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"referral"}],"note":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"POST","path":"/api/work-orders/operations/{opId}/complete","summary":"Complete an operation.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/clock-on","summary":"Start the clock on a step, for yourself or `workerId`, on the server's clock. Several people may be on one step, each once; the step starts if it had not. Refused on a closed or skipped step. Answers the order's progress, each step listing who is clocked on and since when. `mrp:edit`.","body":{"workerId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/clock-off","summary":"Stop the clock and book its hours through the ordinary step booking, so cost and WIP post exactly as a typed booking would. `finish` closes the step with `qtyCompleted` and any scrap — refused while someone else is still clocked on. A clock that ran past a double shift asks for `hours`, what was really worked. `clientId` makes a retry land once. `mrp:edit`.","body":{"finish":true,"qtyCompleted":4,"workerId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hours":1.5,"qtyScrapped":0.0,"scrapReasonCode":null,"notes":"Stopped for the shift change.","clientId":"8d2f5a61-3c7e-4b90-a1d4-6e9b2c0f7a15"},"auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"PUT","path":"/api/work-orders/operations/{opId}","summary":"Change a released order's step: its description, work centre, this job's planned setup and run hours, the operator's instructions and notes. Each field left out is left alone; the route is not touched. Moving the step to another centre re-freezes the rates from that centre, and is refused once hours are booked at the old ones. A skipped or closed step is refused. Answers the order's progress. `mrp:edit`.","body":{"plannedRunHours":6.5,"instructions":"Tack all four corners before the long seams.","description":"Weld chassis","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","plannedSetupHours":0.5,"notes":"Jig changed to the new fixture.","scheduledStart":"2026-09-02","scheduledFinish":"2026-09-03"},"auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/skip","summary":"Skip a step this job does not need, with `reason` (required, up to 300 characters). Only a step nobody has touched: once hours or units are booked it is closed, not skipped. A skipped step leaves the capacity load and the schedule, and keeps its reason on the job. Answers the order's progress. `mrp:edit`.","body":{"reason":"Customer collects it unpainted"},"auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/work-orders/operations/{opId}/restore","summary":"Put a skipped step back to pending, clearing its reason. Answers the order's progress. `mrp:edit`.","auth":"jwt","responseExample":{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","status":"sent","productName":"Karoo Fresh Holdings Ltd","routingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routingName":"Karoo Fresh Holdings Ltd","expectedYieldPercent":15.0,"qtyPlanned":1.0,"qtyToStart":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"operations":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","routingOperationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequenceNo":1,"description":"Consulting services — August 2026","workCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","workCentreCode":"CT-001","workCentreName":"Karoo Fresh Holdings Ltd","status":"sent","plannedSetupHours":3.0,"plannedRunHours":3.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"labourRatePerHour":1.0,"overheadRatePerHour":1.0,"actualCost":10005.0,"plannedCost":10005.0,"isSubcontract":false,"subcontractSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subcontractSupplierName":"Karoo Fresh Holdings Ltd","scheduledStart":"2026-09-01","scheduledFinish":"text","startedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","operatorName":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year."}],"operationCount":3,"completedOperationCount":3,"percentComplete":15.0,"plannedHours":3.0,"actualHours":3.0,"varianceHours":3.0,"actualLabourCost":10005.0,"currentOperation":"text"},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/work-in-progress","summary":"The open WIP balance by job. This is what reconciles the WIP control account to the floor. jobs and openJobCount stay wire names.","auth":"jwt","responseExample":{"totalWip":10005.0,"openJobCount":3,"jobs":[{"workOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","woNumber":"INV-0001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","status":"sent","qtyPlanned":1.0,"qtyCompleted":1.0,"qtyScrapped":1.0,"stdMaterialPerUnit":1.0,"stdLabourPerUnit":1.0,"stdOverheadPerUnit":1.0,"stdTotalPerUnit":10005.0,"stdHoursPerUnit":3.0,"stdLabourRate":15.0,"standardCostOfOutput":10005.0,"actualMaterial":1.0,"actualLabour":1.0,"actualOverhead":1.0,"actualTotal":10005.0,"actualHours":3.0,"wipRelieved":1.0,"wipVarianceCleared":1.0,"wipBalance":10005.0,"totalVariance":10005.0,"variances":[{"type":"standard","label":"Karoo Fresh Holdings Ltd","amount":10005.0,"accountCode":"CT-001","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","standardQty":3.0,"actualQty":3.0,"standardRate":15.0,"actualRate":15.0,"explanation":"text","favourable":false,"journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"issues":[],"labour":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hours":3.0,"actualRate":15.0,"actualCost":10005.0,"standardRate":15.0,"overheadCost":10005.0,"entryType":"standard","entryDate":"2026-09-01","employeeName":"Thandi Mokoena","notes":"Budget deferred to the next financial year.","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"hasRouting":false,"standardPinned":false,"completions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyCompleted":1.0,"qtyScrapped":1.0,"standardUnitCost":2900.0,"standardTotal":10005.0,"isFinal":false,"completedAt":"2026-09-01T09:15:00Z","completedByName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","reversedAt":"2026-09-01T09:15:00Z","reversalOfId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reversalReason":"Budget deferred to the next financial year.","qtyStillInStock":1.0,"canReverse":false}]}],"ledgerWip":1.0,"controlDifference":1.0},"module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"GET","path":"/api/standard-costs","summary":"Stored standard-cost results.","auth":"jwt","responseKind":"json","module":"mrp","plan":"Manufacturing","scope":"mrp:read"},{"method":"PUT","path":"/api/standard-costs","summary":"Override a standard cost by hand.","auth":"jwt","responseKind":"json","body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","materialCost":1284.5,"labourCost":10005.0,"overheadCost":10005.0,"labourHoursPerUnit":3.0,"notes":"Budget deferred to the next financial year."},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"POST","path":"/api/standard-costs/roll-up","summary":"Roll the BOM cost up through every level and store the result.","auth":"jwt","responseExample":{"computed":1,"unchanged":1,"standards":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","materialCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"labourHoursPerUnit":3.0,"labourRate":15.0,"costSource":"referral","bomLevel":1,"version":1,"effectiveFrom":"2026-09-01","notes":"Budget deferred to the next financial year."}],"cycles":[["text"]],"warnings":[],"routingsAvailable":false},"body":{"productIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"mrp","plan":"Manufacturing","scope":"mrp:write"},{"method":"GET","path":"/api/standard-costs/{productId}","summary":"One product's standard cost and how it was arrived at.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","bomId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bomName":"Karoo Fresh Holdings Ltd","materialCost":10005.0,"labourCost":10005.0,"overheadCost":10005.0,"totalCost":10005.0,"labourHoursPerUnit":3.0,"labourRate":15.0,"costSource":"bom_rollup","bomLevel":1,"version":1,"effectiveFrom":"2026-09-01","notes":"Budget deferred to the next financial year."}],"module":"mrp","plan":"Manufacturing","scope":"mrp:read"}]},{"name":"Procurement","blurb":"Requisitions and their approval routing, approved vendors, contracts, RFQs, and the three-way match.","endpoints":[{"method":"GET","path":"/api/procurement/overview","summary":"The buyer's dashboard — open requisitions, orders awaiting approval and unmatched receipts.","auth":"jwt","responseExample":{"openRequisitionCount":3,"awaitingApprovalCount":3,"awaitingMyApprovalCount":3,"requisitionValue":10005.0,"openRfqCount":3,"openPoCount":3,"openCommitmentValue":10005.0,"pendingDeliveryCount":3,"overdueDeliveryCount":3,"overdueDeliveryValue":10005.0,"onTimeDeliveryPercent":15.0,"matchExceptionCount":3,"activeContractCount":3,"contractsExpiringCount":3,"approvedVendorCount":3,"blockedVendorCount":3,"productsWithoutVendorCount":3},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/requisitions?status=submitted&awaitingMe=true&q=PR-0001&offset=0","summary":"Requisitions, newest first. `q` searches the number and title; `offset` and `limit` (default 100, at most 500) page through them — the count is at /requisitions/count.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","status":"sent","priority":"normal","requestedByName":"Karoo Fresh Holdings Ltd","requestedFor":"text","requiredDate":"2026-09-01","currency":"ZAR","estimatedTotal":10005.0,"budgetAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","budgetAccountName":"Karoo Fresh Holdings Ltd","budgetRemaining":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreName":"Karoo Fresh Holdings Ltd","mrpRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mrpRunNumber":"INV-0001","justification":"text","notes":"Budget deferred to the next financial year.","lineCount":3,"submittedAt":"2026-09-01T09:15:00Z","approvedAt":"2026-09-01T09:15:00Z","rejectedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","estimatedUnitPrice":2900.0,"estimatedTotal":10005.0,"suggestedSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","suggestedSupplierName":"Karoo Fresh Holdings Ltd","plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","notes":"Budget deferred to the next financial year.","approvedVendorCount":3}],"approvals":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stepNo":1,"approverLabel":"Thandi Mokoena","approverRoleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approverUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent","decidedByName":"Thandi Mokoena","decidedAt":"2026-09-01T09:15:00Z","comment":"Budget deferred to the next financial year.","canDecide":false}],"currentStep":1,"awaitingMe":false,"purchaseOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/requisitions/count?status=submitted&q=gas","summary":"How many requisitions the list would page through for the same status and search — the figure behind 'Showing 100 of 106'.","auth":"jwt","responseExample":{"total":106},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/requisitions","summary":"Raise a requisition.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"clientId":"ec4ecf4b-712e-5979-806d-127d1b370ec8","title":"Karoo Fresh Holdings Ltd","priority":"normal","requestedFor":"2026-10-15","requiredDate":"2026-09-10","currency":"ZAR","budgetAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","justification":"Stock for the October production run","notes":"Budget deferred to the next financial year.","lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","estimatedUnitPrice":84.5,"suggestedSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year."}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/requisitions/{id}","summary":"One requisition and its approval trail.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","status":"sent","priority":"normal","requestedByName":"Karoo Fresh Holdings Ltd","requestedFor":"text","requiredDate":"2026-09-01","currency":"ZAR","estimatedTotal":10005.0,"budgetAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","budgetAccountName":"Karoo Fresh Holdings Ltd","budgetRemaining":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreName":"Karoo Fresh Holdings Ltd","mrpRunId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","mrpRunNumber":"INV-0001","justification":"text","notes":"Budget deferred to the next financial year.","lineCount":3,"submittedAt":"2026-09-01T09:15:00Z","approvedAt":"2026-09-01T09:15:00Z","rejectedAt":"2026-09-01T09:15:00Z","rejectionReason":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","estimatedUnitPrice":2900.0,"estimatedTotal":10005.0,"suggestedSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","suggestedSupplierName":"Karoo Fresh Holdings Ltd","plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","notes":"Budget deferred to the next financial year.","approvedVendorCount":3}],"approvals":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stepNo":1,"approverLabel":"Thandi Mokoena","approverRoleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approverUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent","decidedByName":"Thandi Mokoena","decidedAt":"2026-09-01T09:15:00Z","comment":"Budget deferred to the next financial year.","canDecide":false}],"currentStep":1,"awaitingMe":false,"purchaseOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/requisitions/{id}/submit","summary":"Submit for approval.","auth":"jwt","responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/requisitions/{id}/approve","summary":"Approve at the caller's level in the routing.","auth":"jwt","responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/requisitions/{id}/reject","summary":"Reject, with a reason.","auth":"jwt","body":{"comment":"Stock already on order"},"responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/requisitions/{id}/cancel","summary":"Cancel a requisition.","auth":"jwt","responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/requisitions/{id}/purchase-orders","summary":"Turn an approved requisition into purchase orders, split by vendor.","auth":"jwt","responseExample":{"purchaseOrderIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"purchaseOrderNumbers":["PO-0001"],"lineCount":3,"totalValue":10005.0,"skipped":[{"plannedOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"priceBreakOpportunities":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","supplierName":"Karoo Fresh Holdings Ltd","orderedQty":3.0,"orderedUnitPrice":2900.0,"orderedTotal":10005.0,"breakQty":3.0,"breakUnitPrice":2900.0,"breakTotal":10005.0,"extraUnits":1.0,"saving":1.0}]},"body":{"fxRate":18.5,"lineIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"supplierByLineId":{"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"singleSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","expectedDate":"2026-09-01","contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","approveImmediately":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/approval-rules","summary":"The approval routing — who approves what, at what value.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","stepNo":1,"minAmount":10005.0,"maxAmount":10005.0,"approverRoleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approverRoleName":"Karoo Fresh Holdings Ltd","approverUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approverUserName":"Karoo Fresh Holdings Ltd","budgetAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/approval-rules","summary":"Add an approval rule.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"productCategory":"hardware","supplierId":"edaf88e6-33ef-5aaa-8def-1138f7029bda","clientId":"28431a10-e640-5b59-a80b-412e9ecc424f","name":"Karoo Fresh Holdings Ltd","stepNo":2,"minAmount":10005.0,"maxAmount":50000.0,"approverRoleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","approverUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","budgetAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","isActive":true},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"DELETE","path":"/api/procurement/approval-rules/{id}","summary":"Remove an approval rule.","auth":"jwt","responseExample":{"status":"deleted"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/approval-rules/options","summary":"Who an approval rule may name (people and roles that can approve purchases), and the cost centres and item categories a rule may be narrowed to.","auth":"jwt","responseExample":{"users":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","roleName":"Karoo Fresh Holdings Ltd"}],"roles":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"costCentres":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"categories":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/approval-delegations","summary":"Cover while an approver is away: who stands in for whom, from when to when.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userName":"Thandi Mokoena","delegateUserId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","delegateName":"Karoo Fresh Holdings Ltd","startsOn":"2026-09-01","endsOn":"2026-09-01","reason":"Budget deferred to the next financial year.","activeToday":true}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/approval-delegations","summary":"Appoint a stand-in who may decide what waits on an approver for a period. Your own cover needs approval rights; somebody else's needs edit rights.","auth":"jwt","body":{"userId":"5f2f93c3-4b3f-50c5-bba9-61121084fc0c","clientId":"dd58eddb-21ff-5cfe-9b7b-4251193a1cfa","delegateUserId":"b8fb24bf-f65e-5730-8c45-a314ee0bb216","startsOn":"2026-10-01","endsOn":"2026-10-14","reason":"Annual leave"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"DELETE","path":"/api/procurement/approval-delegations/{id}","summary":"End a stand-in's cover early.","auth":"jwt","responseExample":{"status":"deleted"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/replenishment","summary":"Items at or below their reorder point, with the quantity to order from each approved supplier (reorder quantity or shortfall, rounded up to the supplier's minimum and pack size).","auth":"jwt","responseExample":{"groups":[{"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","unit":"each","onHand":1.0,"reorderPoint":1.0,"reorderQty":3.0,"wantedQty":3.0,"suggestedQty":3.0,"minOrderQty":3.0,"orderMultiple":1.0,"unitPrice":2900.0,"lineTotal":8700.0}],"estimatedTotal":10005.0}],"skipped":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/replenishment","summary":"Raise the chosen low-stock items as purchase requests, one per supplier, optionally sent straight into approval.","auth":"jwt","body":{"productIds":["4ea78728-ddfd-5b57-8fd4-e58dca8360d6"],"submit":true},"responseExample":{"requisitions":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","lineCount":3,"estimatedTotal":10005.0,"status":"sent"}],"skipped":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/vendors/suppliers","summary":"Supplier contacts an approved-vendor line may name, for the add-a-vendor picker.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/vendors/{id}/status","summary":"Block, unblock or mark a vendor row provisional — the status alone; its price, SKU, contract, validity, notes and preferred flag are left as they are.","auth":"jwt","body":{"status":"blocked"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"blocked","isPreferred":true},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/vendors?productId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"Approved vendors with their ratings and B-BBEE levels.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","supplierSku":"LEN-TP-14G4","status":"sent","isPreferred":false,"priority":100,"unitPrice":2900.0,"currency":"ZAR","leadTimeDays":30,"minOrderQty":3.0,"orderMultiple":1.0,"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","validFrom":"2026-09-01","validTo":"2026-09-30","onTimeReceipts":1,"lateReceipts":1,"onTimePercent":15.0,"priceBreakCount":3,"unavailableReason":"Budget deferred to the next financial year.","notes":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/vendors","summary":"Approve a supplier as a vendor, or change their standing. On an existing vendor, a field left out keeps its stored value.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","productName":"Karoo Fresh Holdings Ltd","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","supplierSku":"LEN-TP-14G4","status":"sent","isPreferred":false,"priority":100,"unitPrice":2900.0,"currency":"ZAR","leadTimeDays":30,"minOrderQty":3.0,"orderMultiple":1.0,"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contractNumber":"INV-0001","validFrom":"2026-09-01","validTo":"2026-09-30","onTimeReceipts":1,"lateReceipts":1,"onTimePercent":15.0,"priceBreakCount":3,"unavailableReason":"Budget deferred to the next financial year.","notes":"Budget deferred to the next financial year."},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierSku":"LEN-TP-14G4","status":"approved","isPreferred":false,"priority":1,"unitPrice":2900.0,"currency":"ZAR","leadTimeDays":30,"minOrderQty":3.0,"orderMultiple":1.0,"contractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","validFrom":"2026-09-01","validTo":"2026-09-30","notes":"Budget deferred to the next financial year."},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"DELETE","path":"/api/procurement/vendors/{id}","summary":"Withdraw vendor approval.","auth":"jwt","responseExample":{"status":"deleted"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/vendors/unsourced","summary":"Parts flagged buy with no approved vendor — the list that stops an MRP run producing a usable answer.","auth":"jwt","responseExample":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","qty":3.0,"sourceType":"invoice","onHand":1.0,"shortfall":1.0,"unitCost":2900.0,"extendedCost":10005.0,"leadTimeDays":30,"supplierName":"Karoo Fresh Holdings Ltd"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/vendors/{id}/price-breaks","summary":"A vendor's quantity price breaks.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","minQty":3.0,"unitPrice":2900.0,"note":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/vendors/{id}/price-breaks","summary":"Set a vendor's price breaks.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","minQty":3.0,"unitPrice":2900.0,"note":"Budget deferred to the next financial year."}],"body":{"breaks":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","minQty":3.0,"unitPrice":79.9,"note":"Budget deferred to the next financial year."}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/contracts","summary":"Supply contracts and their coverage.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","contractNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","contractType":"standard","status":"sent","startDate":"2026-09-01","endDate":"2026-09-30","currency":"ZAR","committedValue":10005.0,"consumedValue":10005.0,"remainingValue":10005.0,"discountPercent":0.0,"paymentTermsDays":30,"bbbeeLevel":1,"incoterms":"text","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","renewalNoticeDays":30,"daysToExpiry":30,"productCount":3}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/contracts","summary":"Record a contract.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"openingConsumedValue":0.0,"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","contractNumber":"SUP-2026-04","contractType":"blanket","status":"draft","startDate":"2026-09-01","endDate":"2027-08-31","currency":"ZAR","committedValue":10005.0,"discountPercent":0.0,"paymentTermsDays":30,"bbbeeLevel":1,"incoterms":"FOB","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","renewalNoticeDays":30},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"PUT","path":"/api/procurement/contracts/{id}/status","summary":"Activate, suspend or close a contract.","auth":"jwt","body":{"status":"active"},"responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/supplier-documents/policy","summary":"Per kind of supplier document: whether a new supplier must upload it when they register, and whether a lapsed one only warns or blocks new purchase orders.","auth":"jwt","responseExample":[{"kind":"invoice","label":"Karoo Fresh Holdings Ltd","expires":true,"consequence":"text","required":true,"onExpiry":"2026-09-30"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/supplier-documents/policy","summary":"Set the rule for one or more kinds of supplier document. A kind that never expires cannot be set to block on expiry.","auth":"jwt","body":{"rules":[{"kind":"tax_clearance","required":true,"onExpiry":"block"}]},"responseExample":[{"kind":"invoice","label":"Karoo Fresh Holdings Ltd","expires":true,"consequence":"text","required":true,"onExpiry":"2026-09-30"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/supplier-registration/link","summary":"The supplier self-registration link to share, whether it is open, and the documents it asks for.","auth":"jwt","responseExample":{"enabled":true,"url":"https://app.ledgrsa.com/pay/3f1a7c92","token":"<never returned>","intro":"text","requiredDocuments":["text"],"unavailableReason":"Budget deferred to the next financial year."},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/supplier-registration/link","summary":"Open or close the registration link, set the note applicants see, or make a new link. Closing or regenerating retires every copy already shared.","auth":"jwt","body":{"enabled":true,"intro":"We buy steel plate and sections for fabrication in Gauteng.","regenerate":false},"responseExample":{"enabled":true,"url":"https://app.ledgrsa.com/pay/3f1a7c92","token":"<never returned>","intro":"text","requiredDocuments":["text"],"unavailableReason":"Budget deferred to the next financial year."},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/supplier-registrations?status=pending","summary":"Applications from businesses that registered through the link, newest first. ?status=submitted (the default), accepted, declined or all.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","companyName":"Karoo Fresh Holdings Ltd","tradingName":"Karoo Fresh Holdings Ltd","registrationNumber":"2021/123456/07","vatNumber":"4123456789","contactName":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","supplies":"text","status":"sent","declineReason":"Budget deferred to the next financial year.","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","submittedAt":"2026-09-01T09:15:00Z","reviewedAt":"2026-09-01T09:15:00Z","documents":[{"kind":"invoice","label":"Karoo Fresh Holdings Ltd","reference":"INV-0001","issuedOn":"2026-09-01","expiresOn":"2026-09-01","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92"}],"missingRequired":["text"],"possibleMatch":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","matchedOn":"2026-09-01"}}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/supplier-registrations/{id}/accept","summary":"Accept an application: it becomes a supplier contact (or joins an existing one), provisionally approved for the items named, with its documents waiting for review. Requires procurement:approve.","auth":"jwt","body":{"productIds":["bb866a9b-544a-5857-b5ef-3dc5e39b4fc7"],"existingContactId":null},"responseExample":{"ok":true,"message":"Saved.","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendorRowCount":3,"applicantEmailed":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/supplier-registrations/{id}/decline","summary":"Decline an application. The reason is required and is emailed to the applicant. Requires procurement:approve.","auth":"jwt","body":{"reason":"We already have two approved steel suppliers in Gauteng."},"responseExample":{"ok":true,"message":"Saved.","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vendorRowCount":3,"applicantEmailed":true},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/rfqs","summary":"Requests for quotation.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","requisitionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","awardedSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awardedSupplierName":"Karoo Fresh Holdings Ltd","awardedQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awardReason":"Budget deferred to the next financial year.","awardedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quotedPrices":[{"quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","unitPrice":2900.0,"lineTotal":8700.0,"leadTimeDays":30,"isLowest":false}]}],"suppliers":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","status":"sent","contactEmail":"accounts@karoofresh.example","sentAt":"2026-09-01T09:15:00Z","respondedAt":"2026-09-01T09:15:00Z","quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteTotal":10005.0}],"quotes":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitPrice":2900.0,"lineTotal":8700.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year."}],"isLowest":false}],"invitedCount":3,"respondedCount":3,"lowestQuoteTotal":10005.0}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/rfqs","summary":"Raise an RFQ.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"clientId":"53d05c7b-38e4-5bf4-b9fe-a6e397a60282","title":"Karoo Fresh Holdings Ltd","requisitionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","responseDueDate":"2026-09-05","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","supplierIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"lines":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"fromRequisitionLines":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/rfqs/{id}","summary":"One RFQ and the quotes received.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","requisitionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","requisitionNumber":"INV-0001","status":"sent","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","awardedSupplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awardedSupplierName":"Karoo Fresh Holdings Ltd","awardedQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","awardReason":"Budget deferred to the next financial year.","awardedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","description":"Consulting services — August 2026","qty":3.0,"unit":"each","requiredDate":"2026-09-01","requisitionLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quotedPrices":[{"quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","unitPrice":2900.0,"lineTotal":8700.0,"leadTimeDays":30,"isLowest":false}]}],"suppliers":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","status":"sent","contactEmail":"accounts@karoofresh.example","sentAt":"2026-09-01T09:15:00Z","respondedAt":"2026-09-01T09:15:00Z","quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteTotal":10005.0}],"quotes":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitPrice":2900.0,"lineTotal":8700.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year."}],"isLowest":false}],"invitedCount":3,"respondedCount":3,"lowestQuoteTotal":10005.0},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/rfqs/{id}/send","summary":"Send the RFQ to its vendors.","auth":"jwt","responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/rfqs/{id}/quotes","summary":"Capture a quote received off-platform.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"clientId":"e271206c-5641-552c-b44d-77d35f1156d4","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","leadTimeDays":30,"paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0,"unitPrice":81.0,"leadTimeDays":7,"notes":"Budget deferred to the next financial year."}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/rfqs/{id}/award","summary":"Award the RFQ and raise the order.","auth":"jwt","responseExample":{"status":"awarded","purchaseOrderIds":"text"},"body":{"lineAwards":[],"quoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reason":"Budget deferred to the next financial year.","addToApprovedVendors":true,"createPurchaseOrder":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/purchase-orders?includeClosed=true&overdueOnly=true","summary":"Purchase orders from the buyer's side, with their transmission state.","auth":"jwt","responseExample":{"asOf":"text","orders":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","number":"INV-0001","supplierName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","total":10005.0,"outstandingValue":10005.0,"lines":[{"lineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyOrdered":1.0,"qtyReceived":1.0,"qtyOutstanding":1.0,"unitPrice":2900.0}],"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receiptCount":3}],"totalOutstanding":10005.0,"openOrderCount":3},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/purchase-orders/{id}/transmit","summary":"Send the order to the vendor.","auth":"jwt","responseExample":{"status":"sent","channel":"email","to":"2026-09-30","number":"INV-0001","delivered":1,"error":"text"},"body":{"channel":"email","to":"2026-09-30","message":"Saved."},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/matches?exceptionsOnly=true","summary":"The three-way match — order against receipt against bill — and what does not agree.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","vendorName":"Karoo Fresh Holdings Ltd","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptNumber":"INV-0001","status":"sent","poTotal":10005.0,"receiptTotal":10005.0,"invoiceTotal":10005.0,"priceVariance":10005.0,"priceVariancePercent":15.0,"qtyVariance":1.0,"toleranceAmount":10005.0,"tolerancePercent":15.0,"lines":[{"description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyReceived":1.0,"qtyBilled":1.0,"lineMatched":false,"priceOrdered":10005.0,"priceReceived":10005.0,"priceVariance":10005.0,"qtyVariance":1.0,"withinTolerance":true,"note":"Budget deferred to the next financial year."}],"matchedAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z","resolvedByName":"Karoo Fresh Holdings Ltd","resolutionNote":"Budget deferred to the next financial year.","blocksPayment":false,"matchBasis":"invoice","overBilledQty":3.0}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/matches/{billId}","summary":"Run the match for one bill.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","vendorName":"Karoo Fresh Holdings Ltd","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptNumber":"INV-0001","status":"sent","poTotal":10005.0,"receiptTotal":10005.0,"invoiceTotal":10005.0,"priceVariance":10005.0,"priceVariancePercent":15.0,"qtyVariance":1.0,"toleranceAmount":10005.0,"tolerancePercent":15.0,"lines":[{"description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyReceived":1.0,"qtyBilled":1.0,"lineMatched":false,"priceOrdered":10005.0,"priceReceived":10005.0,"priceVariance":10005.0,"qtyVariance":1.0,"withinTolerance":true,"note":"Budget deferred to the next financial year."}],"matchedAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z","resolvedByName":"Karoo Fresh Holdings Ltd","resolutionNote":"Budget deferred to the next financial year.","blocksPayment":false,"matchBasis":"invoice","overBilledQty":3.0},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/matches/{billId}/resolve","summary":"Accept or write off a matching difference.","auth":"jwt","body":{"accept":true,"note":"Freight not on the order"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billNumber":"INV-0001","vendorName":"Karoo Fresh Holdings Ltd","purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseOrderNumber":"PO-0001","goodsReceiptId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","goodsReceiptNumber":"INV-0001","status":"sent","poTotal":10005.0,"receiptTotal":10005.0,"invoiceTotal":10005.0,"priceVariance":10005.0,"priceVariancePercent":15.0,"qtyVariance":1.0,"toleranceAmount":10005.0,"tolerancePercent":15.0,"lines":[{"description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyReceived":1.0,"qtyBilled":1.0,"lineMatched":false,"priceOrdered":10005.0,"priceReceived":10005.0,"priceVariance":10005.0,"qtyVariance":1.0,"withinTolerance":true,"note":"Budget deferred to the next financial year."}],"matchedAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z","resolvedByName":"Karoo Fresh Holdings Ltd","resolutionNote":"Budget deferred to the next financial year.","blocksPayment":false,"matchBasis":"invoice","overBilledQty":3.0},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/settings","summary":"Procurement settings — tolerances, required approvals, whether a receipt is mandatory before a bill.","auth":"jwt","responseExample":{"overReceiptTolerancePercent":15.0,"priceTolerancePercent":15.0,"priceToleranceAmount":10005.0,"requireRequisitionForPo":false,"autoApproveBelow":1.0,"minQuotesForAward":1,"defaultPaymentTermsDays":30,"defaultCurrency":"ZAR","requisitionPrefix":"INV-","rfqPrefix":"INV-","workOrderPrefix":"INV-","mrpRunPrefix":"INV-"},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/settings","summary":"Change the procurement settings.","auth":"jwt","responseExample":{"status":"updated"},"body":{"overReceiptTolerancePercent":15.0,"priceTolerancePercent":2.0,"priceToleranceAmount":10005.0,"requireRequisitionForPo":true,"autoApproveBelow":1.0,"minQuotesForAward":1,"defaultPaymentTermsDays":30,"defaultCurrency":"ZAR","requisitionPrefix":"PR-","rfqPrefix":"RFQ-","workOrderPrefix":"WO-","mrpRunPrefix":"MRP-","matchPaymentHold":"hold"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/bbbee-spend?to=2027-02-28&from=2026-03-01&asOf=2027-02-28","summary":"Preferential procurement spend by supplier B-BBEE level, which feeds the scorecard element.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","asOf":"text","totalMeasuredSpend":10005.0,"recognisedSpend":1.0,"recognisedPercent":15.0,"emeSpend":1.0,"qseSpend":1.0,"blackOwnedSpend":1.0,"blackWomanOwnedSpend":1.0,"unratedSpend":1.0,"expiredSpend":1.0,"recoverableByRenewal":1.0,"supplierCount":3,"lines":[{"supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","spend":1.0,"statedLevel":1,"levelWasDeemed":false,"effectiveLevel":1,"levelLabel":"Karoo Fresh Holdings Ltd","certificateExpiry":"2026-09-30","certificateExpired":false,"recognitionPercent":15.0,"recognisedSpend":1.0,"recoverableByRenewal":1.0,"isEme":false,"isQse":false,"blackOwnedPercent":15.0,"blackWomanOwnedPercent":15.0,"invoiceCount":3}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/suppliers/{id}/bbbee","summary":"Record a supplier's B-BBEE level and certificate expiry.","auth":"jwt","responseExample":{"status":"saved"},"body":{"level":2,"certificateExpiry":"2027-03-31","isEme":true,"isQse":true,"blackOwnedPercent":15.0,"blackWomanOwnedPercent":15.0,"certificateRef":"INV-0001"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/products?q=cup","summary":"The products a purchase request line, an approved vendor or a supplier's catalogue item may name — id, SKU, name, whether stock is tracked and the product's units. The same list as /api/bom/products, read under procurement:view, because a tenant on Business with the Procurement add-on does not license BOM.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"CUP-250","name":"Paper cup 250ml (sleeve of 50)","isTracked":true}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/coding-options","summary":"The cost centres and GL accounts a purchase may be coded to, for the active company.","auth":"jwt","responseExample":{"costCentres":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","kind":"standard"}],"accounts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","name":"Karoo Fresh Holdings Ltd","kind":"standard"}]},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/purchase-orders/{id}/coding","summary":"Re-code a draft purchase order: its cost centre and each line's own cost centre and account.","auth":"jwt","body":{"accountId":"4a1215ab-22f9-50b3-b002-723ec48c343a","costCentreId":"0a4f4aa1-b7dc-59cc-9cd4-fd01927b8fb9","lines":[{"lineId":"d71b9f56-9052-56b1-9fef-274c088c6a22","costCentreId":"46533f02-0b9e-5375-9cba-aad23feb4122","accountId":"e65cd49a-04f4-5eff-8eb5-7743db4252f2"}]},"responseExample":{"status":"coded"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/budgets","summary":"Every procurement budget and where it stands: actual, committed and what is left.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","periodStart":"2026-09-01","periodEnd":"2026-09-30","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountName":"Karoo Fresh Holdings Ltd","costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","costCentreName":"Karoo Fresh Holdings Ltd","amount":10005.0,"policy":"fifo","actual":1.0,"committed":1.0,"available":1.0,"usedPercent":15.0,"summary":"Consulting services — August 2026"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/budgets","summary":"Add a procurement budget for an account, a cost centre or both, with what happens when a purchase would go over.","auth":"jwt","body":{"accountId":"2985214f-008c-50a0-b2a3-4850d0b8bb4f","clientId":"6ee6a6e0-afda-5f5c-aedd-4fe2f848a739","name":"Workshop, September","periodStart":"2026-09-01","periodEnd":"2026-09-30","costCentreId":"cdb8606e-8257-5a0c-a39d-633747284541","amount":25000.0,"policy":"require_approval"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"PUT","path":"/api/procurement/budgets/{id}","summary":"Change a procurement budget.","auth":"jwt","body":{"costCentreId":"eaf3783a-41a3-5564-a39e-3c489f6f649f","clientId":"3252abdc-b93e-50af-9881-91bd27e15407","name":"Workshop, September","periodStart":"2026-09-01","periodEnd":"2026-09-30","accountId":"269c4a12-cd72-586e-93c2-fdcd713cdb6e","amount":30000.0,"policy":"warn"},"responseExample":{"status":"saved"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"DELETE","path":"/api/procurement/budgets/{id}","summary":"Remove a procurement budget.","auth":"jwt","responseExample":{"status":"deleted"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/requisitions/{id}/budget-impact","summary":"What a purchase request does to each budget it touches.","auth":"jwt","responseExample":[{"budgetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","budgetName":"Karoo Fresh Holdings Ltd","policy":"fifo","budget":1.0,"actual":1.0,"committed":1.0,"thisPurchase":1.0,"available":1.0,"remainingAfter":1.0,"overBy":1.0,"exceeded":true,"needsExtraApproval":true,"summary":"Consulting services — August 2026","approvalStatus":"sent","canDecide":true,"decisionComment":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/punchout-suppliers","summary":"The suppliers whose own web shop a requisition can open — each one with punch-out set up and switched on.","auth":"jwt","responseExample":[{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","protocol":"text"}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/suppliers/{contactId}/punchout","summary":"A supplier's punch-out set-up: cXML or OCI, the shop's set-up address and the identities it expects. The shared secret is never returned; hasSecret says whether one is held.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","protocol":"text","setupUrl":"https://app.ledgrsa.com/pay/3f1a7c92","fromIdentity":"text","toIdentity":"text","senderIdentity":"text","username":"text","hasSecret":false,"active":false,"configured":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"PUT","path":"/api/procurement/suppliers/{contactId}/punchout","summary":"Set up punch-out to a supplier's shop. The set-up address must be https. A blank sharedSecret keeps the one held; the secret is stored encrypted.","auth":"jwt","responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","protocol":"text","setupUrl":"https://app.ledgrsa.com/pay/3f1a7c92","fromIdentity":"text","toIdentity":"text","senderIdentity":"text","username":"text","hasSecret":false,"active":false,"configured":false},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"POST","path":"/api/procurement/requisitions/{id}/punchout","summary":"Open the supplier's shop from a draft requisition. Answers the address to open; the cart the shop sends back becomes lines on this requisition at the cart's prices, and the requisition stays a draft for its approval rules. The return address is good once, for an hour.","auth":"jwt","responseExample":{"startUrl":"https://app.ledgrsa.com/pay/3f1a7c92","expiresInMinutes":60},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/purchase-orders/{id}/budget-impact","summary":"What a purchase order does to each budget it touches, and whether an overspend is waiting on a decision.","auth":"jwt","responseExample":[{"budgetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","budgetName":"Karoo Fresh Holdings Ltd","policy":"fifo","budget":1.0,"actual":1.0,"committed":1.0,"thisPurchase":1.0,"available":1.0,"remainingAfter":1.0,"overBy":1.0,"exceeded":true,"needsExtraApproval":true,"summary":"Consulting services — August 2026","approvalStatus":"sent","canDecide":true,"decisionComment":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/purchase-orders/{id}/budget-approval/{budgetId}","summary":"Agree to, or decline, a purchase order's overspend on one budget. Declining needs a reason.","auth":"jwt","body":{"approve":false,"comment":"Hold this until the March budget opens"},"responseExample":{"status":"sent"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/spend?groupBy=supplier&from=2026-09-01&to=2026-09-30&limit=25","summary":"Posted supplier spend and open order value grouped by supplier, category, cost centre or month, against the period before.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","previousFrom":"2026-09-01","previousTo":"2026-09-30","groupBy":"text","totalPosted":10005.0,"totalPreviousPosted":10005.0,"totalCommitted":10005.0,"changePercent":15.0,"rows":[{"key":"text","label":"Karoo Fresh Holdings Ltd","posted":1.0,"previousPosted":1.0,"committed":1.0,"changePercent":15.0,"sharePercent":15.0}],"groupCount":3,"otherPosted":1.0,"otherCommitted":1.0},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"GET","path":"/api/procurement/spend/price-trend?from=2026-01-01&to=2026-09-30&productId=af7cd2b6-edec-51be-a94d-f4afee91aba0&limit=10","summary":"The price paid per product over time, from goods receipts.","auth":"jwt","responseExample":{"from":"2026-09-01","to":"2026-09-30","products":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sku":"LEN-TP-14G4","name":"Karoo Fresh Holdings Ltd","receiptCount":3,"quantity":3.0,"spend":1.0,"firstUnitCost":2900.0,"lastUnitCost":2900.0,"minUnitCost":2900.0,"maxUnitCost":2900.0,"averageUnitCost":2900.0,"changePercent":15.0,"points":[{"date":"2026-09-01","unitCost":2900.0,"qty":3.0,"supplierName":"Karoo Fresh Holdings Ltd"}]}],"productCount":3},"module":"procurement","plan":"Manufacturing","scope":"procurement:read"}]},{"name":"Supplier portal API","blurb":"A supplier holds a token scoped to one contacts row, sent to this JSON API as a bearer HEADER; the supplier's own pages (Supplier portal pages) carry the same token in the path. Revocation is a generation counter, and the per-supplier opt-in is checked on every request. The other half is what a supplier opens on their own initiative: their price list, their compliance paperwork, an offer nobody asked for, a despatch advice, and what they are owed. None of it writes stock, a ledger entry or an approval — the buyer reads it and chooses to act.","endpoints":[{"method":"GET","path":"/supplier-api/v1/session","summary":"Who the token belongs to, which buyer they are dealing with, and what they may see.","auth":"supplier-token","responseExample":{"supplierName":"Karoo Fresh Holdings Ltd","buyerName":"Karoo Fresh Holdings Ltd","buyerCompanyName":"Karoo Fresh Holdings Ltd","currency":"ZAR","ordersAwaitingAcknowledgement":1,"openOrders":1,"openRfqs":1,"invoicesAwaitingAcceptance":1,"accessExpiresAt":"2026-09-01T09:15:00Z","complianceNeedingAttention":1,"liveOffers":1,"adoptedCatalogueItems":1,"overdueInvoices":1,"overdueAmount":10005.0}},{"method":"GET","path":"/supplier-api/v1/orders","summary":"Purchase orders addressed to this supplier.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]}]},{"method":"GET","path":"/supplier-api/v1/orders/{id}","summary":"One order with its lines and delivery requirements.","auth":"supplier-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]}},{"method":"POST","path":"/supplier-api/v1/orders/{id}/acknowledge","summary":"Acknowledge an order, with a promised date.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"decision":"accepted","signedBy":"Thandi Mokoena","promisedDate":"2026-09-08","note":"Full quantity available"}},{"method":"GET","path":"/supplier-api/v1/rfqs","summary":"RFQs this supplier has been invited to.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}]},{"method":"GET","path":"/supplier-api/v1/rfqs/{id}","summary":"One RFQ and its lines.","auth":"supplier-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},{"method":"POST","path":"/supplier-api/v1/rfqs/{id}/quote","summary":"Submit a quote against an RFQ.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"quoteNumber":"INV-0001","validUntil":"2027-03-31","leadTimeDays":30,"paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","clientReference":"rfq-quote-0001","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":81.0,"leadTimeDays":7,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}},{"method":"GET","path":"/supplier-api/v1/invoices","summary":"Invoices this supplier has submitted, and their state.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},{"method":"POST","path":"/supplier-api/v1/invoices","summary":"Submit an invoice against an order. It arrives as a bill for the buyer to match, never as an approved payable.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"purchaseOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"ACME-8841","issueDate":"2026-09-09","dueDate":"2026-10-01","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":500.0,"unitPrice":81.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"note":"Budget deferred to the next financial year.","clientReference":"INV-0001"}},{"method":"POST","path":"/supplier-api/v1/invoices/{id}/withdraw","summary":"Withdraw a submitted invoice before the buyer processes it.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}}},{"method":"GET","path":"/supplier-api/v1/catalogue","summary":"The supplier's own price list, and which of their prices the buyer is ordering against.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","supplierSku":"LEN-TP-14G4","unit":"each","unitPrice":2900.0,"currency":"ZAR","minOrderQty":3.0,"orderMultiple":1.0,"leadTimeDays":30,"status":"sent","statusLabel":"Karoo Fresh Holdings Ltd","validFrom":"2026-09-01","validUntil":"2026-09-30","notes":"Budget deferred to the next financial year.","priceBreaks":[{"minQty":3.0,"unitPrice":2900.0,"note":"Budget deferred to the next financial year."}],"buyerProductName":"Karoo Fresh Holdings Ltd","updatedAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/supplier-api/v1/catalogue","summary":"Add or correct one price-list item. Keyed on the supplier's own SKU, so re-sending a price list updates rather than duplicating.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"12mm mild steel plate","supplierSku":"MS-12-2412","unit":"each","unitPrice":1840.0,"minOrderQty":4.0,"orderMultiple":4.0,"leadTimeDays":5,"validFrom":"2026-09-01","validUntil":"2026-09-30","notes":"Budget deferred to the next financial year.","priceBreaks":[{"minQty":20.0,"unitPrice":1755.0,"note":"Budget deferred to the next financial year."}]}},{"method":"POST","path":"/supplier-api/v1/catalogue/{id}/withdraw","summary":"Stop offering an item. Withdrawn rather than deleted, so a price quoted last month stays explicable.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}}},{"method":"GET","path":"/supplier-api/v1/compliance","summary":"What is on file, what is about to lapse, and what the buyer has never had — the missing list included, because a supplier cannot send a document nobody asked for.","auth":"supplier-token","responseExample":{"documents":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","consequence":"text","reference":"INV-0001","issuedOn":"2026-09-01","expiresOn":"2026-09-01","state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","daysUntilExpiry":30,"claimedBbbeeLevel":1,"reviewNote":"Budget deferred to the next financial year.","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","submittedAt":"2026-09-01T09:15:00Z"}],"missing":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","consequence":"text","reference":"INV-0001","issuedOn":"2026-09-01","expiresOn":"2026-09-01","state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","daysUntilExpiry":30,"claimedBbbeeLevel":1,"reviewNote":"Budget deferred to the next financial year.","fileUrl":"https://app.ledgrsa.com/pay/3f1a7c92","submittedAt":"2026-09-01T09:15:00Z"}],"bbbeeSpendClaimable":false,"attention":["text"]}},{"method":"GET","path":"/supplier-api/v1/registration","summary":"The supplier self-registration form: whose link it is, their note, and the documents they require. Carries the registration link's token as a bearer header.","auth":"supplier-token","responseExample":{"buyerName":"Karoo Fresh Holdings Ltd","intro":"text","requiredDocuments":[{"kind":"invoice","label":"Karoo Fresh Holdings Ltd","expires":true,"consequence":"text"}],"optionalDocuments":[{"kind":"invoice","label":"Karoo Fresh Holdings Ltd","expires":true,"consequence":"text"}],"maxDocumentBytes":1}},{"method":"POST","path":"/supplier-api/v1/registration/upload","summary":"Upload the scan of one document for a registration, up to 8MB. Returns an attachment id to quote on the application. The server decides the content type, never the client.","auth":"supplier-token","responseExample":{"attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sizeBytes":1}},{"method":"POST","path":"/supplier-api/v1/registration","summary":"Send a supplier registration: company details, VAT and CIPC numbers, a contact, and the uploaded documents. No bank details are taken. It changes nothing until the business accepts it.","auth":"supplier-token","body":{"tradingName":"Karoo Gas Supplies","phone":"+27 21 555 0142","address":"14 Voortrekker Road, Bellville, 7530","companyName":"Steelco (Pty) Ltd","registrationNumber":"2019/123456/07","vatNumber":"4123456784","contactName":"Thandi Mokoena","email":"tenders@steelco.example","supplies":"Steel plate and sections","documents":[{"kind":"tax_clearance","attachmentId":"22e0b355-9548-5a94-bdda-2c708df386f5","reference":"TCS-0042","expiresOn":"2027-03-31"}]},"responseExample":{"reference":"INV-0001","message":"Saved."}},{"method":"POST","path":"/supplier-api/v1/compliance/upload","summary":"Upload the scan of a document, up to 8MB. Returns an attachment id to quote on the submit. The server decides the content type, never the client.","auth":"supplier-token","responseExample":{"attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sizeBytes":"text"}},{"method":"POST","path":"/supplier-api/v1/compliance","summary":"File a compliance document. It arrives as submitted and changes nothing until a person accepts it; a B-BBEE level is held as a CLAIM until then.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"kind":"bbbee_certificate","reference":"VA-2026-00184","issuedOn":"2026-03-01","expiresOn":"2027-02-28","claimedBbbeeLevel":4,"claimedBlackOwnedPercent":15.0,"claimedBlackWomanOwnedPercent":15.0,"claimedIsEme":false,"claimedIsQse":false,"attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},{"method":"GET","path":"/supplier-api/v1/offers","summary":"Offers this supplier has made unasked, with the buyer's outcome and whether each may still be revised.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","title":"Karoo Fresh Holdings Ltd","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","net":8700.0,"vat":1305.0,"gross":1.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","statusLabel":"Karoo Fresh Holdings Ltd","revision":1,"withdrawn":false,"outcomeNote":"Budget deferred to the next financial year.","canRevise":false,"revisionRefusal":"text","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}],"notes":"Budget deferred to the next financial year."}]},{"method":"POST","path":"/supplier-api/v1/offers","summary":"Send a price nobody asked for, or revise one already sent. Idempotent on clientReference — two prices for the same work in front of a buyer is worse than a duplicate invoice.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"clientReference":"offer-4471","title":"Steelwork, Bellville warehouse","quoteNumber":"INV-0001","validUntil":"2026-10-15","leadTimeDays":10,"paymentTermsDays":30,"notes":"Budget deferred to the next financial year.","lines":[{"description":"Portal frames","quantity":40.0,"unitPrice":8750.0,"vatRatePercent":15.0,"vatInclusive":false,"discountPercent":0.0,"supplierSku":"LEN-TP-14G4","unit":"each","minOrderQty":3.0,"leadTimeDays":30}],"revisesQuoteId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},{"method":"POST","path":"/supplier-api/v1/offers/{id}/withdraw","summary":"Take an offer off the table. A different fact from the buyer rejecting it, so it does not overwrite the status.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}}},{"method":"GET","path":"/supplier-api/v1/orders/{id}/despatchable","summary":"What may still be declared as sent on an order — netting off what has been received AND what is already in transit.","auth":"supplier-token","responseExample":[{"poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyReceived":1.0,"qtyAlreadyDespatched":1.0,"qtyRemaining":1.0,"unit":"each"}]},{"method":"POST","path":"/supplier-api/v1/orders/{id}/despatch","summary":"Declare that goods have left. Moves no stock and costs nothing; it pre-fills the buyer's goods receipt and gives their expediting screen a real arrival date.","auth":"supplier-token","responseExample":{"ok":true,"message":"Saved.","order":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","issueDate":"2026-09-01","expectedDate":"2026-09-01","status":"sent","currency":"ZAR","subtotal":8700.0,"vatTotal":1305.0,"total":10005.0,"deliveryAddress":"12 Long Street, Cape Town, 8001","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","productCode":"CT-001","quantity":3.0,"qtyReceived":1.0,"unitPrice":2900.0,"vatRate":15.0,"lineTotal":10005.0}],"acknowledgedAt":"2026-09-01T09:15:00Z","acknowledgedBy":"text","ackStatus":"sent","promisedDate":"2026-09-01","ackNote":"Budget deferred to the next financial year.","canAcknowledge":false,"canInvoice":false,"submittedInvoices":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]},"invoice":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","net":8700.0,"vat":1305.0,"gross":1.0,"currency":"ZAR","status":"sent","submittedAt":"2026-09-01T09:15:00Z","orderNumber":"PO-0001","lines":[{"description":"Consulting services — August 2026","poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quantity":3.0,"unitPrice":2900.0,"vatRate":15.0,"vatInclusive":false,"lineTotal":10005.0,"vatAmount":1305.0}],"canWithdraw":false,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."},"rfq":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rfqNumber":"INV-0001","title":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","responseDueDate":"2026-09-01","currency":"ZAR","deliveryAddress":"12 Long Street, Cape Town, 8001","terms":"Goods remain the property of the seller until paid in full.","notes":"Budget deferred to the next financial year.","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","lineNumber":1,"description":"Consulting services — August 2026","quantity":3.0,"unit":"each","requiredDate":"2026-09-01"}],"invitationStatus":"sent","canQuote":false,"submittedQuote":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","currency":"ZAR","subtotal":8700.0,"vatAmount":1305.0,"total":10005.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"rfqLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"leadTimeDays":30,"notes":"Budget deferred to the next financial year.","lineTotal":10005.0}]}}},"body":{"clientReference":"asn-9912","despatchedOn":"2026-09-10","expectedArrival":"2026-09-12","carrier":"Own vehicle","waybill":"WB-33417","notes":"Budget deferred to the next financial year.","lines":[{"poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qty":40.0}]}},{"method":"GET","path":"/supplier-api/v1/despatches","summary":"Deliveries this supplier has declared, and whether each has been booked in.","auth":"supplier-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","despatchedOn":"2026-09-01","expectedArrival":"text","carrier":"text","waybill":"text","status":"sent","statusLabel":"Karoo Fresh Holdings Ltd","notes":"Budget deferred to the next financial year.","lines":[{"poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0}],"complete":false}]},{"method":"GET","path":"/supplier-api/v1/statement","summary":"What the supplier is owed, when it falls due, and the payables control's verdict on anything held — from the buyer's own books.","auth":"supplier-token","responseExample":{"currency":"ZAR","awaitingAcceptance":1.0,"notYetDue":1.0,"overdue":1.0,"paidLast90Days":1.0,"nextDueDate":"2026-09-01","nextDueAmount":10005.0,"lines":[{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","issueDate":"2026-09-01","dueDate":"2026-10-01","gross":1.0,"status":"sent","positionLabel":"Karoo Fresh Holdings Ltd","daysUntilDue":30,"matchStatus":"sent","matchNote":"Budget deferred to the next financial year."}]}},{"method":"GET","path":"/supplier-api/v1/scorecard","summary":"The supplier's own on-time rating, quote win rate and spend. The same figures the buyer's vendor list draws — a rating a supplier cannot see is one they cannot improve.","auth":"supplier-token","responseExample":{"deliveriesScored":1,"onTimeDeliveries":1,"onTimePercent":15,"quotesSubmitted":1,"quotesWon":1,"winRatePercent":15,"spendLast12Months":1.0,"currency":"ZAR","openOrders":1,"openOrderValue":10005.0}}]},{"name":"Supplier workspace, buyer side","blurb":"The buyer's half of what a supplier sends through /supplier-api/v1. Without these the portal's writes land in tables nobody reads, and a supplier who sends something into a void stops sending. Every write here is a PERSON deciding: adopting a catalogue item copies it into approved_vendors rather than aliasing it, and accepting a B-BBEE document is the only thing that writes the supplier's B-BBEE level.","endpoints":[{"method":"GET","path":"/api/procurement/supplier-offers?includeClosed=true","summary":"Quotes suppliers sent without being asked. Kept apart from RFQ responses, which belong beside their competitors.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","title":"Karoo Fresh Holdings Ltd","quoteNumber":"INV-0001","quoteDate":"2026-09-01","validUntil":"2026-09-30","expired":false,"net":8700.0,"vat":1305.0,"gross":1.0,"leadTimeDays":30,"paymentTermsDays":30,"status":"sent","revision":1,"withdrawnBySupplier":false,"notes":"Budget deferred to the next financial year.","lines":[{"description":"Consulting services — August 2026","supplierSku":"LEN-TP-14G4","quantity":3.0,"unit":"each","unitPrice":2900.0,"vatRate":15.0,"discountRate":0.0,"lineTotal":10005.0,"minOrderQty":3.0,"leadTimeDays":30}]}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/supplier-offers/{id}/decide","summary":"Accept or decline an offer. A reason is required on a decline and the supplier reads it — 'we went elsewhere' with no reason is why suppliers stop quoting.","auth":"jwt","body":{"outcome":"decline","note":"Went with a shorter lead time."},"responseExample":{"ok":"true","message":"Saved."},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/supplier-catalogue?supplierId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&status=active","summary":"What suppliers say they sell, with their volume breaks and order multiples.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","supplierSku":"LEN-TP-14G4","unit":"each","unitPrice":2900.0,"currency":"ZAR","minOrderQty":3.0,"orderMultiple":1.0,"leadTimeDays":30,"status":"sent","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","priceBreaks":[{"minQty":3.0,"unitPrice":2900.0}],"validFrom":"2026-09-01","validUntil":"2026-09-30","notes":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/supplier-catalogue/{id}/adopt","summary":"Take an offered item into the approved source list. COPIES the figures, so a supplier editing their catalogue afterwards cannot move a price you have contracted at.","auth":"jwt","responseExample":{"ok":"true","message":"$out is now an approved source at the supplier's price."},"body":{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/supplier-compliance","summary":"Every supplier's paperwork with its expiry and what lapses with it — the 30-day question is a WHERE clause on one date.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","kind":"invoice","kindLabel":"Karoo Fresh Holdings Ltd","consequence":"text","reference":"INV-0001","issuedOn":"2026-09-01","expiresOn":"2026-09-01","daysUntilExpiry":30,"state":"sent","status":"sent","claimedBbbeeLevel":1,"submittedBySupplier":false,"submittedAt":"2026-09-01T09:15:00Z","fileId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reviewNote":"Budget deferred to the next financial year."}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"},{"method":"POST","path":"/api/procurement/supplier-compliance/{id}/review","summary":"Accept or reject a document. Accepting a B-BBEE certificate is the ONLY thing that writes contacts.bbbee_level, because an unverified level is an audit finding against the buyer who claimed the spend.","auth":"jwt","responseExample":{"ok":"true","message":"Saved."},"body":{"outcome":"accept","note":"Budget deferred to the next financial year."},"module":"procurement","plan":"Manufacturing","scope":"procurement:write"},{"method":"GET","path":"/api/procurement/incoming-despatches?includeReceived=true","summary":"What suppliers say is on its way, with a real expected arrival rather than a date typed at ordering time. Nothing here has moved any stock.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","orderNumber":"PO-0001","supplierId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","supplierName":"Karoo Fresh Holdings Ltd","despatchedOn":"2026-09-01","expectedArrival":"text","daysUntilArrival":30,"carrier":"text","waybill":"text","status":"sent","notes":"Budget deferred to the next financial year.","lines":[{"poLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qty":3.0}]}],"module":"procurement","plan":"Manufacturing","scope":"procurement:read"}]},{"name":"Logistics & fleet","blurb":"A TRIP is the parent, not the delivery note — one vehicle carries eight customers' goods, and one document is routinely delivered across two stops on two days. The proof belongs to the STOP.","endpoints":[{"method":"GET","path":"/api/logistics/vehicles/{id}/fuel","summary":"A vehicle's fill-ups, newest first, with its consumption measured fill to fill and a sentence when that has jumped.","auth":"jwt","responseExample":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","litresPer100Km":1.0,"warning":"text","fills":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filledOn":"2026-09-01","litres":1.0,"amount":10005.0,"odometerKm":1.0,"garage":"text","cardRef":"INV-0001","source":"referral","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/fuel","summary":"Record a fill-up. Posts one zero-rated fuel expense; links to the vehicle's trip that day. Send clientReference and a retry lands once.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filledOn":"2026-09-01","litres":1.0,"amount":10005.0,"odometerKm":1.0,"garage":"text","cardRef":"INV-0001","source":"office","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filledOn":"2026-09-01","litres":62.4,"amount":1310.4,"odometerKm":184320.0,"garage":"Rivonia Road service station","cardRef":"FC-4471","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientReference":"0b9e4d2a-7c31-4f58-a6e0-5d2c8f1b3e47"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/fuel/import","summary":"A fuel-card statement pasted as text; columns are found by their headings (date, registration, litres, amount, odometer, merchant, card). Each line lands once; every line that could not is named by its number.","auth":"jwt","responseExample":{"recorded":1,"problems":[]},"body":{"text":"date,registration,litres,amount,odometer,merchant,card\n2026-09-01,CA 123-456,62.4,1310.40,184320,Rivonia Road service station,FC-4471\n2026-09-03,CA 123-456,58.1,1220.10,184905,N1 Kraaifontein fuel stop,FC-4471"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/settings","summary":"The company's Logistics settings: the number drivers reach the office on, and the company phone they reach when it is not set.","auth":"jwt","responseExample":{"officePhone":"+27 82 555 0143","companyPhone":"+27 82 555 0143"},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/settings","summary":"Set the number drivers reach the office on (null or blank falls back to the company's phone). Refused unless it can be a phone number.","auth":"jwt","body":{"officePhone":"011 555 0100"},"responseExample":{"officePhone":"+27 82 555 0143","companyPhone":"+27 82 555 0143"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/tracking/settings","summary":"How fresh the live map is: while a trip is running, each driver's phone sends its position every flushSeconds (60 to 120). Needs the Driver-tracking add-on.","auth":"jwt","responseExample":{"flushSeconds":120,"minSeconds":60,"maxSeconds":120},"module":"driver-tracking","addon":"Live driver & truck tracking","scope":"driver-tracking:read"},{"method":"PUT","path":"/api/logistics/tracking/settings","summary":"Choose how often a phone on a running trip sends its position, 60 to 120 seconds. Outside a trip nothing is sent, whatever this says. Needs the Driver-tracking add-on.","auth":"jwt","body":{"flushSeconds":60},"responseExample":{"flushSeconds":60,"minSeconds":60,"maxSeconds":120},"module":"driver-tracking","addon":"Live driver & truck tracking","scope":"driver-tracking:write"},{"method":"GET","path":"/api/logistics/dispatch?date=2027-02-28&waitingPage=1","summary":"One day on the dispatch board: a lane per vehicle with the trip it is on that day, what that trip carries against the vehicle, and whether a load may be dropped on it; and the loads waiting: those due at the door on or before the day (overdue first, then by customer), a page of 100 with waitingTotal beside it, ?waitingPage=n for the next; and the loads with no delivery date apart (undated, undatedTotal). ?date=yyyy-MM-dd, today in South Africa when absent.","auth":"jwt","responseExample":{"date":"2026-09-01","lanes":[{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripStatus":"sent","driverName":"Thandi Mokoena","stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"label":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001"}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]},"acceptsLoads":true,"note":"Budget deferred to the next financial year."}],"waiting":[{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","deliveryDate":"2026-09-01","address":"12 Long Street, Cape Town, 8001","city":"Cape Town","postalCode":"CT-001","lineCount":3,"totalQty":3.0,"total":10005.0,"currency":"ZAR"}],"waitingTotal":42,"waitingPage":1,"undated":[{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","address":"12 Long Street, Cape Town, 8001","city":"Cape Town","postalCode":"CT-001","lineCount":3,"totalQty":3.0,"total":10005.0,"currency":"ZAR"}],"undatedTotal":42},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/stops/{id}/location","summary":"Place a stop at a point the office chose — typed coordinates or a pasted map link. With saveToContact (the default) the point also becomes the contact's delivery location, so the next stop built there carries it. A stop with an outcome is part of the record and cannot be moved.","auth":"jwt","body":{"latitude":-29.8587,"longitude":31.0218,"saveToContact":true},"responseExample":{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","latitude":1.0,"longitude":1.0,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactLocationSource":"referral"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/proofs/{id}/learn-location","summary":"Save the fix a driver's phone took with this proof as the contact's delivery location. Offered, never automatic: only a fix the phone claimed to within 100 m, and never over a location a person placed.","auth":"jwt","responseExample":{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","latitude":1.0,"longitude":1.0,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactLocationSource":"referral"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/geocode","summary":"Candidate points for a street address, for a person to choose one and place it. Nothing is stored. Refused when street maps are not configured on this deployment; every lookup is a billed call, so it needs edit permission.","auth":"jwt","body":{"address":"12 Smith Street, Durban"},"responseExample":{"candidates":[{"label":"Karoo Fresh Holdings Ltd","latitude":1.0,"longitude":1.0,"approximate":true}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/compliance/expiring","summary":"Licences and discs expiring: every licence disc, roadworthy, operator card, driving licence and PrDP at or inside its 60-day reminder (60, 30, 7 and 0 days), expired first, with whether the list can be emailed and why not.","auth":"jwt","responseExample":{"asOf":"text","horizonDays":30,"summary":"Consulting services — August 2026","items":[{"holder":"vehicle","holderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","holderName":"Karoo Fresh Holdings Ltd","document":"text","documentLabel":"Karoo Fresh Holdings Ltd","expiresOn":"2026-09-01","days":30,"stage":"text","stageLabel":"Karoo Fresh Holdings Ltd","sentence":"text"}],"emailAvailable":false,"emailBlockedReason":"Budget deferred to the next financial year."},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/compliance/expiring/email","summary":"Email the expiring list to the fleet controllers (users whose role edits Logistics) and the owner, now. On demand only; refused in words when the notification switch is off, email is not set up, nothing is due or nobody can receive it.","auth":"jwt","responseExample":{"sent":1,"recipients":["text"],"message":"Saved."},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/servicing","summary":"Every vehicle still on the fleet against its service plan (every N km or N months, whichever first): last service, next due by distance and date, and a sentence saying where it stands.","auth":"jwt","responseExample":[{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","everyKm":1,"everyMonths":1,"standingCostPerKm":10005.0,"odometerKm":1.0,"lastServiceOn":"2026-09-01","lastServiceKm":1.0,"state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","dueAtKm":1.0,"dueOn":"2026-09-01","kmLeft":1.0,"daysLeft":30,"estimatedOn":"2026-09-01","sentence":"text"}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/vehicles/{id}/service","summary":"A vehicle's service sheet: its plan, its service log, what it cost this year (every purchase allocated to it that reached the ledger, fuel included) and those purchases.","auth":"jwt","responseExample":{"plan":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","everyKm":1,"everyMonths":1,"standingCostPerKm":10005.0,"odometerKm":1.0,"lastServiceOn":"2026-09-01","lastServiceKm":1.0,"state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","dueAtKm":1.0,"dueOn":"2026-09-01","kmLeft":1.0,"daysLeft":30,"estimatedOn":"2026-09-01","sentence":"text"},"entries":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serviceOn":"2026-09-01","odometerKm":1.0,"kind":"standard","kindLabel":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseLabel":"Karoo Fresh Holdings Ltd","costExVat":1305.0,"inspectionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"costThisYear":10005.0,"purchases":[{"kind":"expense","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amountExVat":1305.0,"linkedToService":false}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/vehicles/{id}/service-plan","summary":"Set a vehicle's service plan and its standing cost per km. Blank clears; both intervals blank is no plan.","auth":"jwt","body":{"everyKm":15000,"everyMonths":12,"standingCostPerKm":2.35,"costPerKmIncludesFuel":false},"responseExample":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","everyKm":1,"everyMonths":1,"standingCostPerKm":10005.0,"odometerKm":1.0,"lastServiceOn":"2026-09-01","lastServiceKm":1.0,"state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","dueAtKm":1.0,"dueOn":"2026-09-01","kmLeft":1.0,"daysLeft":30,"estimatedOn":"2026-09-01","sentence":"text"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/vehicle-services","summary":"Log a service, repair or tyres. Either links a purchase already allocated to the vehicle or records the workshop's invoice here as an ordinary expense on the vehicle; never both. The odometer reading moves the vehicle's forward. Send clientReference and a retry lands once.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serviceOn":"2026-09-01","odometerKm":1.0,"kind":"standard","kindLabel":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","purchaseLabel":"Karoo Fresh Holdings Ltd","costExVat":1305.0,"inspectionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","serviceOn":"2026-09-01","odometerKm":1.0,"kind":"service","description":"Consulting services — August 2026","costExVat":1305.0,"vatCharged":true,"supplier":"Karoo Fresh Holdings Ltd","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","inspectionId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientReference":"INV-0001"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/inspection-checklist","summary":"The company's pre-trip checklist, in order, and the standard list it can start from. Empty means drivers are asked nothing.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd"}],"standard":["text"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/inspection-checklist","summary":"Replace the pre-trip checklist, in order. An empty list switches the check off; answers already given keep the wording the driver read.","auth":"jwt","body":{"labels":["Tyres and wheel nuts","Lights and indicators","Brakes"]},"responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd"}],"standard":["text"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips/{id}/inspections","summary":"A trip's pre-trip checks as the driver answered them, newest first: each answer with the wording read, what failed, and the office's decision.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverName":"Thandi Mokoena","state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","answers":[{"itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","passed":true,"note":"Budget deferred to the next financial year."}],"failedItems":["text"],"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/trips/{id}/inspection/decision","summary":"Answer a failed pre-trip check: allow (the trip may start and the vehicle returns to the road) or keep_off_road (the vehicle stays In for repair; the trip needs another vehicle).","auth":"jwt","body":{"decision":"allow"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverName":"Thandi Mokoena","state":"sent","stateLabel":"Karoo Fresh Holdings Ltd","answers":[{"itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd","passed":true,"note":"Budget deferred to the next financial year."}],"failedItems":["text"],"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","decidedAt":"2026-09-01T09:15:00Z","decidedByName":"Thandi Mokoena"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips/{id}/cost","summary":"What a run cost: fuel (its fills), purchases allocated to the trip, driver hours at each driver's cost per hour and the vehicle's standing cost per km; cost per km and per drop; the stops' delivery charges and the margin; and in words, any part that could not be counted.","auth":"jwt","responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","distanceKm":1.0,"drops":1,"driverHours":3.0,"fuel":1.0,"other":1.0,"labour":1.0,"standing":1.0,"total":10005.0,"perKm":1.0,"perDrop":1.0,"revenue":1.0,"margin":1.0,"marginPercent":15.0,"gaps":["text"],"lines":[{"kind":"fuel","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"name":"Karoo Fresh Holdings Ltd","status":"sent","charge":1.0}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/costs?from=2026-03-01&to=2027-02-28","summary":"Every run in the period with its cost, and the period's cost per km, per drop and margin. ?from&to=yyyy-MM-dd, the last 30 days when absent.","auth":"jwt","responseExample":{"fromDate":"2026-09-01","toDate":"2026-09-01","runs":[{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","distanceKm":1.0,"drops":1,"driverHours":3.0,"fuel":1.0,"other":1.0,"labour":1.0,"standing":1.0,"total":10005.0,"perKm":1.0,"perDrop":1.0,"revenue":1.0,"margin":1.0,"marginPercent":15.0,"gaps":["text"],"lines":[{"kind":"fuel","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"name":"Karoo Fresh Holdings Ltd","status":"sent","charge":1.0}]}],"total":10005.0,"distanceKm":1.0,"drops":1,"perKm":1.0,"perDrop":1.0,"revenue":1.0,"margin":1.0,"incompleteRuns":1},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/trips/{id}/costs","summary":"A cost paid on the run — a toll, parking, a tyre — recorded as an ordinary expense on the trip and its vehicle, posted like any other. clientId becomes the expense id, so a retry lands once.","auth":"jwt","responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","distanceKm":1.0,"drops":1,"driverHours":3.0,"fuel":1.0,"other":1.0,"labour":1.0,"standing":1.0,"total":10005.0,"perKm":1.0,"perDrop":1.0,"revenue":1.0,"margin":1.0,"marginPercent":15.0,"gaps":["text"],"lines":[{"kind":"fuel","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"name":"Karoo Fresh Holdings Ltd","status":"sent","charge":1.0}]},"body":{"description":"Consulting services — August 2026","amountExVat":1305.0,"vatCharged":false,"date":"2026-09-01","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/stops/{id}/charge","summary":"What the customer is charged for this drop, for the run's margin. Null clears it.","auth":"jwt","body":{"deliveryCharge":350.0},"responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","distanceKm":1.0,"drops":1,"driverHours":3.0,"fuel":1.0,"other":1.0,"labour":1.0,"standing":1.0,"total":10005.0,"perKm":1.0,"perDrop":1.0,"revenue":1.0,"margin":1.0,"marginPercent":15.0,"gaps":["text"],"lines":[{"kind":"fuel","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0}],"stops":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"name":"Karoo Fresh Holdings Ltd","status":"sent","charge":1.0}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/drivers/{id}/cost-rate","summary":"What an hour of this driver costs, for a run's cost. Null clears it.","auth":"jwt","body":{"costPerHour":85.0},"responseExample":{"costPerHour":10005.0},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/standing-runs","summary":"The company's standing runs: name, vehicle, driver, cadence (weekly, fortnightly, monthly), ordered stops with contact, window and instructions, and the next days each raises a trip on.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","startsOn":"2026-09-01","endsOn":"2026-09-01","active":true,"notes":"Budget deferred to the next financial year.","stops":[{"stopType":"standard","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."}],"nextRuns":["text"]}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/standing-runs","summary":"Create a standing run. Its trips are raised on demand when a planner opens a day on the dispatch board — once per run per day, and never for a day already gone. clientId makes a retry land once.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","startsOn":"2026-09-01","endsOn":"2026-09-01","active":true,"notes":"Budget deferred to the next financial year.","stops":[{"stopType":"standard","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."}],"nextRuns":["text"]},"body":{"runDays":[1,3,5],"name":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","cadence":"weekly","startsOn":"2026-09-01","endsOn":"2026-09-01","active":true,"notes":"Budget deferred to the next financial year.","stops":[{"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/standing-runs/{id}","summary":"Change a standing run; its stops are replaced as a block. Trips already raised keep what they were raised with.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","cadence":"text","cadenceLabel":"Karoo Fresh Holdings Ltd","startsOn":"2026-09-01","endsOn":"2026-09-01","active":true,"notes":"Budget deferred to the next financial year.","stops":[{"stopType":"standard","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."}],"nextRuns":["text"]},"body":{"runDays":[1,3,5],"name":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","cadence":"weekly","startsOn":"2026-09-01","endsOn":"2026-09-01","active":true,"notes":"Budget deferred to the next financial year.","stops":[{"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"DELETE","path":"/api/logistics/standing-runs/{id}","summary":"Stop a standing run. The trips it already raised stay.","auth":"jwt","responseExample":{"status":"deleted"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/stops/{id}/customer","summary":"The stop's customer: the tracking and proof-of-delivery links to hand them (relative paths, valid 90 days), every update they were sent or that is waiting, their rating, and whether they asked not to be told.","auth":"jwt","responseExample":{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","trackPath":"text","podPath":"text","linkValidDays":30,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","updatesOptedOut":false,"notices":[{"event":"dispatched","channel":"email","status":"queued","recipient":"text","detail":"Saved.","at":"2026-09-01T09:15:00Z"}],"rating":1,"ratingComment":"Budget deferred to the next financial year.","ratedAt":"2026-09-01T09:15:00Z"},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/stops/{id}/customer/revoke","summary":"Retire every link this stop's customer holds — tracking, proof and rating at once — and answer with the new ones.","auth":"jwt","responseExample":{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","trackPath":"text","podPath":"text","linkValidDays":30,"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","contactEmail":"accounts@karoofresh.example","contactPhone":"+27 82 555 0143","updatesOptedOut":false,"notices":[{"event":"dispatched","channel":"email","status":"queued","recipient":"text","detail":"Saved.","at":"2026-09-01T09:15:00Z"}],"rating":1,"ratingComment":"Budget deferred to the next financial year.","ratedAt":"2026-09-01T09:15:00Z"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/contacts/{id}/delivery-updates","summary":"Stop (optedOut true) or resume delivery updates to one contact, on every channel, from now on.","auth":"jwt","body":{"optedOut":true},"responseExample":{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","optedOut":true},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/documents/{id}/deliveries","summary":"How a document went out: one row per stop that carried it, with the line Invoicing shows — \"Delivered in full — signed by …\", and \"signed\" only when a signature was captured. Needs invoices:view.","auth":"jwt","responseExample":[{"stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","line":"text","proofId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","receivedByName":"Karoo Fresh Holdings Ltd","capturedAt":"2026-09-01T09:15:00Z"}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/board","summary":"Every vehicle with its state, its current trip and how long since its phone last reported. The screen a fleet controller leaves open. lastPosition (where the vehicle is) is filled only for a tenant holding the Live driver & truck tracking add-on; lastSeenMinutes is filled for every Logistics tenant.","auth":"jwt","responseExample":[{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","vehicleType":"standard","state":"sent","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripStatus":"sent","routeName":"Karoo Fresh Holdings Ltd","stopsDone":1,"stopsTotal":42,"lastPosition":{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"referral","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1},"lastSeenMinutes":1,"complianceWarning":"text"}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/summary","summary":"Today's counts, plus what expires in 30 days — the licence disc, the certificate of fitness, the operator card, the driver's licence and the PrDP.","auth":"jwt","responseExample":{"vehiclesActive":1,"vehiclesOnTrip":1,"vehiclesInMaintenance":1,"driversActive":1,"tripsToday":1,"tripsInProgress":1,"stopsToday":1,"stopsDeliveredToday":1,"stopsFailedToday":1,"stopsOutstandingToday":1,"unassignedDocuments":1,"podCapturePercent":15.0,"podEvidencePercent":15.0,"complianceAlerts":1,"currency":"ZAR"},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/performance?from=2026-08-01&to=2026-08-31","summary":"On-time delivery, failure reasons, distance and cost per trip.","auth":"jwt","responseExample":{"fromDate":"2026-09-01","toDate":"2026-09-01","stopsAttempted":1,"delivered":1,"partial":1,"failed":0,"successPercent":15.0,"onTimePercent":15.0,"podCapturePercent":15.0,"strongProofs":1,"adequateProofs":1,"weakProofs":1,"failureReasons":[{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"Office supplies","count":3,"chargeable":false}],"byDriver":[{"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","trips":1,"stopsAttempted":1,"delivered":1,"failed":0,"podCapturePercent":15.0}],"byVehicle":[{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","trips":1,"distanceKm":1.0,"stopsDelivered":1,"fuelLitres":1.0,"fuelCost":10005.0,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR"}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/unassigned?kind=returns","summary":"Documents ready to deliver that no trip has picked up.","auth":"jwt","responseExample":[{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","issueDate":"2026-09-01","deliveryDate":"2026-09-01","address":"12 Long Street, Cape Town, 8001","city":"Cape Town","postalCode":"CT-001","lineCount":3,"totalQty":3.0,"total":10005.0,"currency":"ZAR"}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/vehicles?includeRetired=true&search=cape","summary":"Vehicles with their SA compliance dates as columns rather than a generic documents table.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","make":"text","model":"text","year":2026,"vehicleType":"standard","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"sent","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","homeLocationName":"Karoo Fresh Holdings Ltd","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","soonestComplianceExpiryDays":30,"soonestComplianceExpiryKind":"standard","onTrip":false,"currentTripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","currentTripNumber":"INV-0001","lastPosition":{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"referral","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1}}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/vehicles","summary":"Add a vehicle. The operator card applies to goods vehicles over 3 500kg under the NRTA.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","make":"text","model":"text","year":2026,"vehicleType":"bakkie","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"active","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","homeLocationName":"Karoo Fresh Holdings Ltd","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","soonestComplianceExpiryDays":30,"soonestComplianceExpiryKind":"standard","onTrip":false,"currentTripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","currentTripNumber":"INV-0001","lastPosition":{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"driver_app","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1}},"body":{"registration":"CA 123-456","fleetNumber":"INV-0001","make":"Toyota","model":"Hilux 2.4 GD-6","year":2026,"vehicleType":"bakkie","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"active","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/vehicles/{id}","summary":"One vehicle with its trip and position history.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","make":"text","model":"text","year":2026,"vehicleType":"standard","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"sent","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","homeLocationName":"Karoo Fresh Holdings Ltd","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","soonestComplianceExpiryDays":30,"soonestComplianceExpiryKind":"standard","onTrip":false,"currentTripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","currentTripNumber":"INV-0001","lastPosition":{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"referral","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1}},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/vehicles/{id}","summary":"Update a vehicle.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","fleetNumber":"INV-0001","make":"text","model":"text","year":2026,"vehicleType":"bakkie","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"active","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","homeLocationName":"Karoo Fresh Holdings Ltd","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","soonestComplianceExpiryDays":30,"soonestComplianceExpiryKind":"standard","onTrip":false,"currentTripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","currentTripNumber":"INV-0001","lastPosition":{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"driver_app","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1}},"body":{"registration":"CA 123-456","fleetNumber":"INV-0001","make":"Toyota","model":"Hilux 2.4 GD-6","year":2026,"vehicleType":"bakkie","payloadKg":1.0,"volumeM3":1.0,"palletCapacity":1,"odometerKm":1.0,"fuelType":"standard","tankLitres":1.0,"licenceDiscExpiry":"2026-09-30","roadworthyExpiry":"2026-09-30","operatorCardExpiry":"2026-09-30","status":"active","homeLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fixedAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"DELETE","path":"/api/logistics/vehicles/{id}","summary":"Retire a vehicle.","auth":"jwt","responseExample":{"status":"deleted"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/drivers?includeInactive=true","summary":"Drivers with their licence code and PrDP category.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"text","prdpExpiry":"2026-09-30","status":"sent","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultVehicleRegistration":"text","notes":"Budget deferred to the next financial year.","soonestDocumentExpiryDays":30,"soonestDocumentExpiryKind":"standard","appAccessIssued":false,"appAccessRevokedAt":"2026-09-01T09:15:00Z","appLastSeenAt":"2026-09-01T09:15:00Z","openTrips":1}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/drivers","summary":"Add a driver. A driver is NOT a user account — the product deliberately does not meter seats, and a seat per driver would break that.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"text","prdpExpiry":"2026-09-30","status":"active","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultVehicleRegistration":"text","notes":"Budget deferred to the next financial year.","soonestDocumentExpiryDays":30,"soonestDocumentExpiryKind":"standard","appAccessIssued":false,"appAccessRevokedAt":"2026-09-01T09:15:00Z","appLastSeenAt":"2026-09-01T09:15:00Z","openTrips":1},"body":{"settlementBasis":"drop","settlementRate":35,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"G","prdpExpiry":"2026-09-30","status":"active","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/drivers/{id}","summary":"Update a driver.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"text","prdpExpiry":"2026-09-30","status":"active","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultVehicleRegistration":"text","notes":"Budget deferred to the next financial year.","soonestDocumentExpiryDays":30,"soonestDocumentExpiryKind":"standard","appAccessIssued":false,"appAccessRevokedAt":"2026-09-01T09:15:00Z","appLastSeenAt":"2026-09-01T09:15:00Z","openTrips":1},"body":{"settlementBasis":"drop","settlementRate":35,"supplierContactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"G","prdpExpiry":"2026-09-30","status":"active","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"DELETE","path":"/api/logistics/drivers/{id}","summary":"Retire a driver.","auth":"jwt","responseExample":{"status":"deleted"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/drivers/{id}/app-token?days=30","summary":"Mint a driver-app credential. Returned ONCE and never retrievable; issuing a new one retires whatever that driver is holding, by bumping drivers.portal_token_version. Add ?days= to shorten the 90-day default.","auth":"jwt","responseExample":{"token":"<driver-token, shown once>","driverId":"87ba03ee-c9f4-5884-b84e-cdd9ff79c69d","expiresAt":"2026-11-20T00:00:00Z"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/drivers/{id}/app-token/revoke","summary":"Retire the driver's token now. A JWT is valid until it expires by construction; nothing else can retire one already on a phone.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fullName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","email":"accounts@karoofresh.example","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","employeeNumber":"INV-0001","licenceNumber":"INV-0001","licenceCode":"CT-001","licenceExpiry":"2026-09-30","prdpNumber":"INV-0001","prdpCategories":"text","prdpExpiry":"2026-09-30","status":"sent","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultVehicleRegistration":"text","notes":"Budget deferred to the next financial year.","soonestDocumentExpiryDays":30,"soonestDocumentExpiryKind":"standard","appAccessIssued":false,"appAccessRevokedAt":"2026-09-01T09:15:00Z","appLastSeenAt":"2026-09-01T09:15:00Z","openTrips":1},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips?page=1&status=planned&driverId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&vehicleId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&from=2026-03-01&to=2027-02-28&search=cape&withStops=true","summary":"Trips with their stops and state.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":[]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]}}],"total":42,"page":1,"limit":20,"totalPages":1},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/trips","summary":"Plan a trip — one vehicle, one driver, one run. Numbered from the shared document_sequences series under doc_type 'trip'.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]}},"body":{"tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"2026-10-01T07:00:00Z","plannedReturn":"2026-10-01T16:00:00Z","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips/{id}","summary":"One trip with its ordered stops.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"standard","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"text","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]}}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/trips/{id}","summary":"Change a trip's vehicle, driver or date.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]}},"body":{"tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"2026-10-01T07:00:00Z","plannedReturn":"2026-10-01T16:00:00Z","notes":"Budget deferred to the next financial year.","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"DELETE","path":"/api/logistics/trips/{id}","summary":"Delete a planned trip.","auth":"jwt","responseExample":{"status":"deleted"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/trips/{id}/status","summary":"Move a trip through planned, loading, dispatched, in_progress, completed. Departure and completion both require an odometer reading.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]}},"body":{"status":"sent","odometerKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"reason":"Budget deferred to the next financial year."},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/trips/{id}/stops","summary":"Add a stop that is not a document — a collection, a return, a site visit or the depot leg.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"body":{"linkedCollectionStopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"uom":"each","notes":"Budget deferred to the next financial year."}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireContractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/loads/{documentId}/transfer","summary":"Raise the stock transfer a load's branch is short of — from the supply rule's source when it holds the shortfall, else the nearest branch that does. The load waits on it; a second press raises none.","auth":"jwt","responseExample":{"raised":1,"message":"Transfer raised from Johannesburg — the load waits for it."},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/trips/{id}/stops/from-document","summary":"Add a stop built from a delivery note, invoice, pro-forma or purchase order — all three live in invoices, so one column covers them. Carries the customer, the address and every LINE, which is what lets a short delivery raise a credit note later.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"body":{"documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","windowFrom":"2026-09-01","windowTo":"2026-09-30","instructions":"Budget deferred to the next financial year."},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips/{id}/suggested-sequence","summary":"A shorter order for the run, as advice. Read-only: it reorders nothing. Distances are straight-line between the stops' own coordinates rather than a road route, so the saving is reported and the planner decides; post the ids to /resequence to accept it. Refuses with a reason when the trip has already started, has fewer than three stops, or has fewer than three stops carrying coordinates.","auth":"jwt","responseExample":{"applicable":true,"stopIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"currentDistanceKm":1.0,"suggestedDistanceKm":1.0,"savedKm":1.0,"worthApplying":false,"note":"Budget deferred to the next financial year.","reason":"Budget deferred to the next financial year."},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/trips/{id}/resequence","summary":"Reorder the stops.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","vehicleFleetNumber":"INV-0001","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","coDriverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","coDriverName":"Karoo Fresh Holdings Ltd","status":"sent","routeName":"Karoo Fresh Holdings Ltd","plannedDeparture":"text","actualDeparture":"text","plannedReturn":"text","actualReturn":"text","startOdometerKm":1.0,"endOdometerKm":1.0,"odometerDistanceKm":1.0,"trackedDistanceKm":1.0,"fuelLitres":1.0,"fuelCost":10005.0,"fuelExpenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","cancelledReason":"Budget deferred to the next financial year.","dispatchedAt":"2026-09-01T09:15:00Z","completedAt":"2026-09-01T09:15:00Z","stopCount":3,"stopsCompleted":1,"stopsFailed":0,"stopsWithProof":1,"litresPer100Km":1.0,"costPerDrop":10005.0,"currency":"ZAR","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"load":{"weightKg":1.0,"volumeM3":1.0,"pallets":1,"payloadKg":1.0,"vehicleVolumeM3":1.0,"vehiclePallets":1,"linesWithoutWeight":1,"warnings":[]}},"body":{"stopIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/tracking/trips/{id}","summary":"The trip replay — every stored position in order. Part of the Live driver & truck tracking add-on: a Logistics tenant without it is refused 403 MODULE_NOT_LICENSED.","auth":"jwt","responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","points":[{"latitude":1.0,"longitude":1.0,"accuracyM":1.0,"speedKph":1.0,"headingDeg":1.0,"recordedAt":"2026-09-01T09:15:00Z","receivedAt":"2026-09-01T09:15:00Z","batteryPercent":15,"source":"driver_app","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ageMinutes":1}],"trackedDistanceKm":1.0,"stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}]},"module":"driver-tracking","addon":"Live driver & truck tracking","scope":"driver-tracking:read"},{"method":"GET","path":"/api/logistics/stops/{id}","summary":"One stop with its lines and window.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/stops/{id}","summary":"Change a stop.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","sequence":1,"stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactDisplayName":"Karoo Fresh Holdings Ltd","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentNumber":"INV-0001","documentType":"invoice","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardNumber":"JC-0001","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","status":"sent","enRouteAt":"2026-09-01T09:15:00Z","arrivedAt":"2026-09-01T09:15:00Z","departedAt":"2026-09-01T09:15:00Z","arrivalLatitude":1.0,"arrivalLongitude":1.0,"arrivalAccuracyM":1.0,"arrivalDistanceM":1.0,"exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","exceptionNotes":"Budget deferred to the next financial year.","stockPostedAt":"2026-09-01T09:15:00Z","stockWarnings":["text"],"lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"qtyReturned":1.0,"uom":"each","batchNumber":"INV-0001","stockMovementId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","shortfall":1.0,"qtyLoaded":1.0,"loadCheckedAt":"2026-09-01T09:15:00Z","service":false}],"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"body":{"linkedCollectionStopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopType":"delivery","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","documentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","jobCardId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stockLocationId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"uom":"each","notes":"Budget deferred to the next financial year."}],"clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","hireContractId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"DELETE","path":"/api/logistics/stops/{id}","summary":"Remove a stop.","auth":"jwt","responseExample":{"status":"deleted"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/stops/{id}/proof","summary":"The proof recorded at a stop, with its grade.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"text","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/stops/{id}/proof","summary":"Record the outcome — who received it, the quantities that actually changed hands, and a drawn signature. Where the per-line quantities disagree with the tapped outcome, THE LINES WIN, and a blank line counts as not delivered. distanceFromStopM is computed server-side from two coordinate pairs and never accepted from a client.","auth":"jwt","responseExample":{"proof":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","outcome":"delivered","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","signatureAttachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"distanceFromStopM":1.0,"capturedAt":"2026-09-01T09:15:00Z","recordedAt":"2026-09-01T09:15:00Z","clockSkewMinutes":1,"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","exceptionReasonLabel":"Karoo Fresh Holdings Ltd","photos":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","attachmentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","caption":"Serial plate before fitting","sequence":1}],"capturedInOffice":false,"learnableLocation":false,"strength":"STRONG","evidenceStatement":"text","weaknesses":["text"]},"stopStatus":"sent","duplicate":false,"stockWarnings":["text"],"stockSkippedReason":"Budget deferred to the next financial year."},"body":{"returnables":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","out":10,"back":8}],"temperatures":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","celsius":4.0}],"outcome":"Interested — sending a quote on Friday","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","receivedByIdNumber":"INV-0001","signatureBase64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"capturedAt":"2026-09-01T09:15:00Z","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","lines":[{"stopLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyDelivered":1.0,"qtyReturned":1.0,"batchNumber":"INV-0001","notes":"Budget deferred to the next financial year."}],"clientReference":"INV-0001","collected":{"amount":10005.0,"method":"cash","reference":"INV-0001"}},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/proofs/{id}/photos?caption=Serial%20plate%20before%20fitting","summary":"Attach a photograph to a proof. At most six; the server recompresses.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/proofs/{id}/html","summary":"The proof as a document — who signed, where they stood, when, the quantities, and an honest statement of what the evidence is worth. Do not improve a weak grade's wording.","auth":"jwt","responseKind":"html","module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/exception-reasons?includeInactive=true","summary":"The failure reason list. The seeded set carries LOAD SHEDDING — the most common reason a South African delivery is turned away, and one no other product's standard list has.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"Office supplies","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/exception-reasons","summary":"Add a reason code.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"Office supplies","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true},"body":{"code":"site_closed","label":"Site closed on arrival","category":"customer","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"PUT","path":"/api/logistics/exception-reasons/{id}","summary":"Relabel or retire a reason code.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"Office supplies","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true},"body":{"code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"customer","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/positions","summary":"Post GPS fixes from a third-party tracker. Identify the vehicle by Ledgr's id or by telematicsExternalId, which is the id your own platform already knows it by. A 60s floor is enforced against the previous fix's DEVICE time, future-dated fixes are refused, a batch caps at 500, and what was dropped is reported.","auth":"jwt","responseExample":{"accepted":1,"rejected":0,"reasons":[]},"body":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","telematicsExternalId":"TRK-4092","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","source":"telematics","positions":[{"latitude":-33.9249,"longitude":18.4241,"accuracyM":1.0,"speedKph":62.0,"headingDeg":1.0,"altitudeM":1.0,"recordedAt":"2026-08-25T09:14:00Z","batteryPercent":15,"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/tracking/fleet-map","summary":"The fleet map's framed backdrop plus the vehicles to draw on it. Part of the Live driver & truck tracking add-on: a Logistics tenant without it is refused 403 MODULE_NOT_LICENSED. Send the pixel size you will render at — the server picks the zoom that frames every reporting vehicle inside exactly that box, and the client places markers with the same Web Mercator projection. Answers available=false with a reason, rather than failing, when no maps key is configured. Pass lat, lon and zoom TOGETHER to draw a view the controller has panned or zoomed to instead of the framed one; all three or none, and a view the projection cannot draw is refused rather than quietly replaced with the framed view.","auth":"jwt","responseExample":{"available":false,"unavailableReason":"Budget deferred to the next financial year.","imageUrl":"https://app.ledgrsa.com/pay/3f1a7c92","centreLatitude":1.0,"centreLongitude":1.0,"zoom":1,"widthPx":1,"heightPx":1,"plotted":[{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registration":"text","latitude":1.0,"longitude":1.0}],"attribution":"text"},"module":"driver-tracking","addon":"Live driver & truck tracking","scope":"driver-tracking:read"},{"method":"GET","path":"/api/logistics/delivery-slots","summary":"The delivery windows this company lets customers book on their tracking link, like 08:00-12:00.","auth":"jwt","responseExample":{"slots":["text"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"PUT","path":"/api/logistics/delivery-slots","summary":"Set the delivery windows customers may book. Each is two clock times, the first before the second; at most twelve. An empty list offers none. Needs logistics:edit.","auth":"jwt","body":{"slots":["08:00-12:00","12:00-17:00"]},"responseExample":{"slots":["text"]},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/drivers/{id}/settle","summary":"Settle a contractor driver's period into a draft supplier bill: completed drops, km or hours on their completed trips dated in the period, at their rate, billed as their supplier. 201 with the settlement; 200 with the same bill when this exact period was settled before; 400 for an employee driver (paid through payroll), a driver with no settlement basis, a period overlapping one already settled, a period over 93 days, or nothing to settle. Needs logistics:edit and expenses:create.","auth":"jwt","body":{"from":"2026-10-01","to":"2026-10-31"},"responseExample":{"billId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","basis":"invoice","quantity":3.0,"rate":15.0,"amount":10005.0,"periodFrom":"2026-09-01","periodTo":"2026-09-30","alreadySettled":false},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/trips/{id}/messages","summary":"A trip's thread between the office and its driver, in the order the messages were written (not the order they arrived). Reading it marks the driver's messages delivered. Needs logistics:view.","auth":"jwt","responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","driverName":"Thandi Mokoena","messages":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sender":"office","senderName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","photoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","clientSeq":1,"writtenAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","readAt":"2026-09-01T09:15:00Z"}],"unread":1},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/trips/{id}/messages","summary":"Write to the trip's driver. id is minted by the writer before the first attempt: 201 for a new message, 200 with the stored one on a retry. writtenAt orders the thread; clientSeq orders two written in the same instant. An empty message is refused. Needs logistics:edit.","auth":"jwt","body":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","body":"What is the gate code?","clientSeq":1,"writtenAt":"2026-10-12T08:00:00+02:00"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sender":"office","senderName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","photoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","clientSeq":1,"writtenAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","readAt":"2026-09-01T09:15:00Z"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/trips/{id}/messages/photo?id=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&clientSeq=1&writtenAt=2026-10-12T08%3A00%3A00%2B02%3A00&caption=Gate","summary":"A photo on the trip's thread. Raw image bytes as the body; the message's id, clientSeq, writtenAt and an optional caption on the query. Refused unless the bytes are an image. Needs logistics:edit.","auth":"jwt","responseKind":"json","module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"POST","path":"/api/logistics/trips/{id}/messages/read","summary":"The office has read the thread: every driver message on it is marked read. Needs logistics:edit — a viewer reading the thread does not tell the driver it was read.","auth":"jwt","responseExample":{"read":"text"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"},{"method":"GET","path":"/api/logistics/returnables?contactId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"What each customer holds of each returnable container (crates, pallets, cylinders) — the sum of what drivers counted out less what came back — and its deposit per unit. contactId narrows it to one customer.","auth":"jwt","responseExample":[{"contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactName":"Karoo Fresh Holdings Ltd","productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","productName":"Karoo Fresh Holdings Ltd","balance":10005.0,"depositPerUnit":1.0}],"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"GET","path":"/api/logistics/cash","summary":"Cash collected on delivery and not yet banked, per driver — what 1365 Cash in transit holds. The bank accounts to bank it into come with it for a caller who may bank.","auth":"jwt","responseExample":{"drivers":[{"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","toHandIn":1.0,"collections":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]}],"totalToHandIn":10005.0,"bankAccounts":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd"}],"canBank":false},"module":"logistics","plan":"Manufacturing","scope":"logistics:read"},{"method":"POST","path":"/api/logistics/cash/bank","summary":"Bank a driver's cash: marks the collections banked and posts DR 1350 Bank / CR 1365 Cash in transit. Needs banking:create. An empty collectionIds banks all of the driver's unbanked cash; send clientReference and a retry lands once.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountName":"Karoo Fresh Holdings Ltd","amount":10005.0,"bankedOn":"2026-09-01","reference":"INV-0001","collectionCount":3,"duplicate":false},"body":{"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","bankAccountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","collectionIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"date":"2026-09-01","reference":"INV-0001","clientReference":"INV-0001"},"module":"logistics","plan":"Manufacturing","scope":"logistics:write"}]},{"name":"Driver app API","blurb":"A published contract, outside authenticate(\"jwt-auth\"). Three rules shape it: one request per screen — a driver at a kerbside cannot make a second — nothing to resolve, and every write idempotent.","endpoints":[{"method":"POST","path":"/driver-api/v1/fuel","summary":"A fill-up at the pump, by the driver: only a vehicle they drive (their own, or the one on a trip they are out on). Posts one zero-rated fuel expense; send clientReference and a retry lands once.","auth":"driver-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filledOn":"2026-09-01","litres":1.0,"amount":10005.0,"odometerKm":1.0,"garage":"text","cardRef":"INV-0001","source":"office","expenseId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"body":{"vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filledOn":"2026-09-01","litres":62.4,"amount":1310.4,"odometerKm":184320.0,"garage":"Rivonia Road service station","cardRef":"FC-4471","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientReference":"0b9e4d2a-7c31-4f58-a6e0-5d2c8f1b3e47"}},{"method":"POST","path":"/driver-api/v1/trips/{id}/load-check","summary":"What the driver counted on board before leaving, per stop line (null = not established). Never refuses the departure; the office sees a line that left short. Writing the same check twice leaves the same figures.","auth":"driver-token","responseExample":{"linesRecorded":1,"linesShort":1},"body":{"temperatures":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","celsius":4.0}],"lines":[{"stopLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyLoaded":1.0}]}},{"method":"GET","path":"/driver-api/v1/session","summary":"Who the token belongs to, what vehicle they usually drive, how often to TAKE a position and how often to SEND the batch, and the SERVER's own clock so the app can measure its skew. Send Authorization: Bearer <driver token> — not a user JWT. Sample at positionIntervalSeconds and buffer; POST the batch every positionFlushSeconds. Do not send one fix per request: a fix closer than 60s to the last stored one is refused, and a batch is how a phone that has been out of signal catches up.","auth":"driver-token","responseExample":{"driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","tenantName":"Karoo Fresh Holdings Ltd","companyName":"Karoo Fresh Holdings Ltd","phone":"+27 82 555 0143","defaultVehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","defaultVehicleRegistration":"text","openTripCount":3,"positionIntervalSeconds":1,"positionFlushSeconds":1,"serverTime":"2026-09-01T09:15:00Z","tokenExpiresAt":"2026-09-01T09:15:00Z"}},{"method":"GET","path":"/driver-api/v1/trips","summary":"The trips this driver may act on. Each manifest carries its stops, and each stop its lines, its address and its phone number.","auth":"driver-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","routeName":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","plannedDeparture":"text","startOdometerKm":1.0,"notes":"Budget deferred to the next financial year.","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"stopsTotal":42,"stopsRemaining":1,"preTripChecklist":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd"}],"preTripState":"sent","preTripBlocker":"text"}]},{"method":"GET","path":"/driver-api/v1/trips/{id}","summary":"One manifest.","auth":"driver-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","tripDate":"2026-09-01","status":"sent","routeName":"Karoo Fresh Holdings Ltd","vehicleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","vehicleRegistration":"text","plannedDeparture":"text","startOdometerKm":1.0,"notes":"Budget deferred to the next financial year.","stops":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}}],"stopsTotal":42,"stopsRemaining":1,"preTripChecklist":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Karoo Fresh Holdings Ltd"}],"preTripState":"sent","preTripBlocker":"text"}},{"method":"POST","path":"/driver-api/v1/trips/{id}/start","summary":"Depart, with the odometer the trip's distance is measured from.","auth":"driver-token","responseExample":{"ok":true,"stop":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"tripStatus":"sent","serverTime":"2026-09-01T09:15:00Z","duplicateOfExistingProof":false,"weaknesses":["text"],"strength":"STRONG"},"body":{"odometerKm":184320.0,"inspection":{"clientReference":"6d1f2a90-3b47-4e8c-9f05-1a7c2e4b8d36","answers":[{"itemId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","label":"Tyres and spare","passed":true,"note":"Tread and pressure checked, spare inflated."}],"at":"2026-09-01T09:15:00Z"}}},{"method":"POST","path":"/driver-api/v1/trips/{id}/complete","summary":"Back at the depot. REFUSED while any stop still has no outcome — a trip closed with open stops leaves deliveries neither delivered nor failed, and therefore invisible to both the re-plan list and the failure report.","auth":"driver-token","responseExample":{"ok":true,"stop":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"tripStatus":"sent","serverTime":"2026-09-01T09:15:00Z","duplicateOfExistingProof":false,"weaknesses":["text"],"strength":"STRONG"},"body":{"odometerKm":184520.0,"fuelLitres":62.4,"fuelCost":1310.4}},{"method":"POST","path":"/driver-api/v1/stops/{id}/status","summary":"Mark a stop en route or arrived. The fix at arrival is the first half of the evidence; the geofence allows the device's own claimed error, capped at 150m, because failing an honest driver in a yard with a bad sky view is how a business learns to ignore the flag.","auth":"driver-token","responseExample":{"ok":true,"stop":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"tripStatus":"sent","serverTime":"2026-09-01T09:15:00Z","duplicateOfExistingProof":false,"weaknesses":["text"],"strength":"STRONG"},"body":{"status":"en_route","latitude":1.0,"longitude":1.0,"accuracyM":1.0,"at":"2026-09-01T09:15:00Z"}},{"method":"POST","path":"/driver-api/v1/stops/{id}/proof","summary":"The proof as one offline-safe unit — outcome, receiver, quantities and the drawn signature in a single request. Send the same clientReference on a retry and the STORED proof comes back rather than a second one. captured_at is your clock, recorded_at is the server's; both are kept.","auth":"driver-token","responseExample":{"ok":true,"stop":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sequence":1,"stopType":"standard","status":"sent","customerName":"Karoo Fresh Holdings Ltd","documentNumber":"INV-0001","address":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","latitude":1.0,"longitude":1.0,"contactName":"Karoo Fresh Holdings Ltd","contactPhone":"+27 82 555 0143","instructions":"Budget deferred to the next financial year.","windowFrom":"2026-09-01","windowTo":"2026-09-30","arrivedAt":"2026-09-01T09:15:00Z","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","description":"Consulting services — August 2026","qtyOrdered":1.0,"qtyDelivered":1.0,"uom":"each","batchNumber":"INV-0001","productBarcode":"6001234567890","qtyLoaded":1.0,"service":false}],"hasProof":false,"collectable":{"invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","amountDue":10005.0,"foreignCurrency":"ZAR"},"collection":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","stopId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoiceNumber":"INV-0001","customerName":"Karoo Fresh Holdings Ltd","paymentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"method":"cash","reference":"INV-0001","collectedAt":"2026-09-01T09:15:00Z","driverId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","driverName":"Thandi Mokoena","bankedAt":"2026-09-01T09:15:00Z","bankingId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},"tripStatus":"sent","serverTime":"2026-09-01T09:15:00Z","duplicateOfExistingProof":false,"weaknesses":["text"],"strength":"STRONG"},"body":{"returnables":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","out":10,"back":8}],"temperatures":[{"productId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","celsius":4.0}],"outcome":"Interested — sending a quote on Friday","receivedByName":"Karoo Fresh Holdings Ltd","receivedByRole":"Accountant","receivedByIdNumber":"INV-0001","signatureBase64":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==","notes":"Budget deferred to the next financial year.","capturedLatitude":1.0,"capturedLongitude":1.0,"capturedAccuracyM":1.0,"capturedAt":"2026-09-01T09:15:00Z","deviceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","exceptionReasonCode":"CT-001","lines":[{"stopLineId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","qtyDelivered":1.0,"qtyReturned":1.0,"batchNumber":"INV-0001","notes":"Budget deferred to the next financial year."}],"clientReference":"INV-0001","collected":{"amount":10005.0,"method":"cash","reference":"INV-0001"}}},{"method":"POST","path":"/driver-api/v1/stops/{id}/proof/photos?caption=Serial%20plate%20before%20fitting&clientId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&proofReference=proofReference","summary":"Attach a photograph to the proof just recorded. Raw image bytes as the body, ?caption= for the label. Send ?clientId= (the id the phone minted for the photograph when it was taken): the first upload answers 201, a retry 200 with the photograph already stored, and an id already used by another proof — or by another business — is refused. ?proofReference= (the proof's clientReference) refuses it when the stop's proof is a different capture.","auth":"driver-token","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}},{"method":"GET","path":"/driver-api/v1/trips/{id}/messages","summary":"The thread with the office for one of this driver's trips, in the order written. Reading it marks the office's messages delivered. Any trip that is not this driver's answers 404.","auth":"driver-token","responseExample":{"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripNumber":"INV-0001","driverName":"Thandi Mokoena","messages":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sender":"office","senderName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","photoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","clientSeq":1,"writtenAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","readAt":"2026-09-01T09:15:00Z"}],"unread":1}},{"method":"POST","path":"/driver-api/v1/trips/{id}/messages","summary":"Write to the office. Idempotent on id, so a message held on the phone in a dead zone lands once however often it is retried (201 new, 200 replay), in the place writtenAt and clientSeq put it. The office is pushed once, unless it has switched driver messages off.","auth":"driver-token","body":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","body":"What is the gate code?","clientSeq":1,"writtenAt":"2026-10-12T08:00:00+02:00"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","sender":"office","senderName":"Karoo Fresh Holdings Ltd","body":"Your invoice INV-0001 is attached.","photoUrl":"https://app.ledgrsa.com/pay/3f1a7c92","clientSeq":1,"writtenAt":"2026-09-01T09:15:00Z","deliveredAt":"2026-09-01T09:15:00Z","readAt":"2026-09-01T09:15:00Z"}},{"method":"POST","path":"/driver-api/v1/trips/{id}/messages/photo?id=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&clientSeq=1&writtenAt=2026-10-12T08%3A00%3A00%2B02%3A00&caption=Gate","summary":"A photo for the office, as a message. Raw image bytes as the body; id, clientSeq, writtenAt and caption on the query. Sent only with signal: the phone does not hold photographs for a message.","auth":"driver-token","responseKind":"json"},{"method":"POST","path":"/driver-api/v1/trips/{id}/messages/read","summary":"The driver opened the thread: the office's messages are read.","auth":"driver-token","responseExample":{"read":"text"}},{"method":"POST","path":"/driver-api/v1/positions","summary":"A batch of fixes, which is how a phone out of signal catches up. The vehicle comes from the driver's open trip and can never be named by the app.","auth":"driver-token","responseExample":{"accepted":1,"rejected":0,"reasons":["Budget deferred to the next financial year."]},"body":{"positions":[{"latitude":-33.9249,"longitude":18.4241,"accuracyM":1.0,"speedKph":48.0,"headingDeg":1.0,"altitudeM":1.0,"recordedAt":"2026-08-25T09:20:00Z","batteryPercent":62,"tripId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}]}},{"method":"GET","path":"/driver-api/v1/exception-reasons","summary":"The failure code list, for offline caching. A driver with no signal and no reason list types \"other\" into a notes field, and a year later the failure report is a reading exercise.","auth":"driver-token","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"CT-001","label":"Karoo Fresh Holdings Ltd","category":"Office supplies","isFailure":true,"isChargeable":false,"sortOrder":1,"active":true}]}]},{"name":"Multi-company & consolidation","blurb":"A tenant may hold several companies. Send X-Company-Id to act within one; company-scoped endpoints reject a request with no company when the tenant has more than one, rather than picking for you.","endpoints":[{"method":"GET","path":"/api/companies?q=cape&offset=0","summary":"Every entity under the tenant. This is the list X-Company-Id is chosen from.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registrationNumber":"2021/123456/07","vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","tradingAs":"text","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","companyType":"PTY","fiscalYearEndMonth":9,"baseCurrency":"ZAR","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false}]},{"method":"POST","path":"/api/companies","summary":"Add an entity. Enterprise and Manufacturing include two; a further one is the extra-company add-on. Company number one is never charged for, and a module you have unlocked applies to EVERY entity rather than being charged again on each. The allowance is checked at CREATE only — a tenant already over it keeps every entity and can go on working in all of them; only a new one is refused, with 409 COMPANY_LIMIT_REACHED.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registrationNumber":"2021/123456/07","vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","tradingAs":"text","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","companyType":"PTY","fiscalYearEndMonth":9,"baseCurrency":"ZAR","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false},"body":{"customsCode":"CC0012345","payrollContactFirstName":"Lerato","payrollContactSurname":"Molefe","payrollContactPhone":"0214441234","payrollContactCell":"0821234567","vatApportionmentPercent":80.0,"vatApportionmentFrom":"2026-10-01","gs1Prefix":"6001234","name":"KMP Cloud (Pty) Ltd","registrationNumber":"2021/123456/07","incorporationDate":"2021-03-15","vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","sic7Code":"62010","pboApproved":false,"pboReference":null,"s18aApproved":false,"specialTrust":false,"tradingAs":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","streetAddress":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","companyType":"PTY","fiscalYearEndMonth":2,"baseCurrency":"ZAR","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownershipPercent":15.0,"consolidationMethod":"FULL","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/companies/{id}","summary":"One entity.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registrationNumber":"2021/123456/07","vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","tradingAs":"text","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","companyType":"PTY","fiscalYearEndMonth":9,"baseCurrency":"ZAR","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false},"scope":"multi-company:read"},{"method":"PUT","path":"/api/companies/{id}","summary":"Update an entity.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","registrationNumber":"2021/123456/07","vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","tradingAs":"text","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","companyType":"PTY","fiscalYearEndMonth":9,"baseCurrency":"ZAR","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false},"body":{"tradingCurrency":"EUR","customsCode":"CC0012345","payrollContactFirstName":"Lerato","payrollContactSurname":"Molefe","payrollContactPhone":"0214441234","payrollContactCell":"0821234567","sharesInventory":true,"sharesPeople":false,"vatApportionmentPercent":80.0,"vatApportionmentFrom":"2026-10-01","gs1Prefix":"6001234","name":"KMP Cloud (Pty) Ltd","registrationNumber":"2021/123456/07","incorporationDate":"2021-03-15","sdlExemption":null,"sdlExemptionReference":null,"vatNumber":"4123456789","vatCategory":"Office supplies","taxNumber":"9012345678","payeNumber":"INV-0001","uifNumber":"INV-0001","sdlNumber":"INV-0001","sic7Code":"62010","pboApproved":false,"pboReference":null,"s18aApproved":false,"specialTrust":false,"tradingAs":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","phone":"+27 82 555 0143","address":"12 Long Street, Cape Town, 8001","streetAddress":"12 Long Street, Cape Town, 8001","suburb":"Woodstock","city":"Cape Town","postalCode":"CT-001","companyType":"PTY","fiscalYearEndMonth":9,"baseCurrency":"ZAR","isActive":true,"parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownershipPercent":15.0,"consolidationMethod":"FULL"},"scope":"multi-company:write"},{"method":"DELETE","path":"/api/companies/{id}","summary":"Remove an entity.","auth":"jwt","responseKind":"none","module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/companies/{id}/partners","summary":"A partnership's partners, their profit shares, largest first, and the annual salary and interest on capital each is allocated before the rest is shared, with the shares' exact total. Any other legal form answers an empty list with partnership=false. Needs multicompany:view, and a company the caller may open.","auth":"jwt","responseExample":{"companyId":"7f6c1a2e-0000-4000-8000-000000000010","partnership":true,"partners":[{"id":"7f6c1a2e-0000-4000-8000-000000000011","name":"Thandi Dlamini","idNumber":"8001015009087","taxNumber":"0123456789","sharePercent":60.0,"effectiveFrom":"2026-03-01","salary":240000.0,"interestOnCapital":12000.0},{"id":"7f6c1a2e-0000-4000-8000-000000000012","name":"Pieter Venter","sharePercent":40.0,"effectiveFrom":"2026-03-01","salary":180000.0,"interestOnCapital":0.0}],"totalPercent":100.0},"scope":"multi-company:read"},{"method":"PUT","path":"/api/companies/{id}/partners","summary":"Replace a partnership's partners with this whole list. A partner sent with their id keeps it (their ITR12 schedule link stays good); one left out is removed. Refused (400, naming the sum) unless there are at least two partners whose shares add up to exactly 100; refused (409) for a company that is not a partnership. `salary` and `interestOnCapital` (annual rand, default 0, never negative) are allocated to the partner before the rest of the profit or loss is shared by the ratio (Income Tax Act s24H(5)(a)); each partner's ITR12 schedule carries them. `effectiveFrom` defaults to today. Needs multicompany:edit.","auth":"jwt","body":{"partners":[{"name":"Thandi Dlamini","taxNumber":"0123456789","sharePercent":60.0,"salary":240000.0,"interestOnCapital":12000.0},{"name":"Pieter Venter","sharePercent":40.0,"salary":180000.0}],"effectiveFrom":"2026-03-01"},"responseExample":{"companyId":"7f6c1a2e-0000-4000-8000-000000000010","partnership":true,"partners":[{"id":"7f6c1a2e-0000-4000-8000-000000000011","name":"Thandi Dlamini","taxNumber":"0123456789","sharePercent":60.0,"effectiveFrom":"2026-03-01","salary":240000.0,"interestOnCapital":12000.0},{"id":"7f6c1a2e-0000-4000-8000-000000000012","name":"Pieter Venter","sharePercent":40.0,"effectiveFrom":"2026-03-01","salary":180000.0,"interestOnCapital":0.0}],"totalPercent":100.0},"module":"sars","plan":"Professional","scope":"multi-company:write"},{"method":"GET","path":"/api/companies/{id}/users","summary":"Who may act in this entity.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","role":"Accountant","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false}],"scope":"multi-company:read"},{"method":"POST","path":"/api/companies/{id}/users","summary":"Grant a user access to this entity. An EMPTY company_users set grants — an owner whose assignments were never seeded must not be locked out.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","role":"Accountant","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false},"body":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","role":"VIEWER","roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"PUT","path":"/api/companies/{id}/users/{userId}/role","summary":"Set a user's role in this entity, or clear it with a null roleId to return them to their organisation role. Needs roles:edit. The owner, the caller and an unassigned user are refused.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","role":"MEMBER","isActive":true,"createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","hasPostedLedger":false,"roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","roleName":"Viewer"},"body":{"roleId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"DELETE","path":"/api/companies/{id}/users/{userId}","summary":"Lift a person's restriction to this entity. Removing their last assignment returns them to every entity in the organisation, and the audit record says so. 404 when they are not restricted to it.","auth":"jwt","responseKind":"none","module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/sandbox","summary":"The API sandbox: a company of sample data inside your own account, for trying the API without touching your real books. Null when you have none. It comes with API access, so it is available only on a plan that includes API keys; available and refusal say whether yours does. The rule is stated in the answer — a sandbox is not counted against the company allowance, you may have one at a time, its name cannot be changed, and it is marked Sandbox wherever it appears.","auth":"jwt","responseExample":{"sandbox":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Sandbox — sample data","label":"Sandbox — sample data","createdAt":"2026-09-01T09:15:00Z"},"rule":"A sandbox company does not count against your plan's company allowance. You may have one at a time; it is marked Sandbox wherever it appears, and deleting it removes every row it holds.","note":"The sandbox is a separate company inside your own account, filled with sample customers, products and invoices that post to its own ledger.","available":true,"refusal":null}},{"method":"POST","path":"/api/sandbox","summary":"Create the sandbox once, seeded with three sample customers, two products and three invoices (paid, open, overdue) posted to its own ledger. Send its id as X-Company-Id to work in it. A second call answers the one you have with created false, rather than making another. Refused with 409 on a plan without API keys, naming the plan that includes them.","auth":"jwt","responseExample":{"sandbox":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Sandbox — sample data","label":"Sandbox — sample data","createdAt":"2026-09-01T09:15:00Z"},"created":true,"message":"Your sandbox is ready. Send its id as X-Company-Id to work in it."}},{"method":"DELETE","path":"/api/sandbox","summary":"Delete the sandbox in one step, with every row it holds and nothing of your real company's. Refused with 409, and nothing deleted, if a record in a real company points at a sandbox record; the refusal names the records that block it.","auth":"jwt","responseExample":{"deletedRows":42,"keptContacts":0,"message":"The sandbox and its 42 rows are gone."}},{"method":"GET","path":"/api/company-hierarchy/tree?rootId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03&parentId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The group structure as a tree, parent to subsidiary.","auth":"jwt","responseExample":{"nodes":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","tradeName":"Karoo Fresh Holdings Ltd","companyType":"standard","baseCurrency":"ZAR","isActive":true,"depth":1,"path":"text","childCount":3,"descendantCount":3,"ownershipPercent":15.0,"effectiveOwnershipPercent":15.0,"consolidationMethod":"eft","orphaned":false}],"tenantCompanyCount":3,"cyclicCompanyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"truncated":false},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/company-hierarchy/picker?q=cape&offset=0&includeInactive=true&parentId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"A searchable flat list for the entity switcher.","auth":"jwt","responseExample":{"items":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","tradeName":"Karoo Fresh Holdings Ltd","depth":1,"breadcrumb":"text","isActive":true,"baseCurrency":"ZAR","childCount":3}],"total":42,"offset":0,"limit":50,"hasMore":true},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/company-hierarchy/{id}/ancestors","summary":"The chain from an entity up to the group head.","auth":"jwt","responseExample":{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ancestors":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","tradeName":"Karoo Fresh Holdings Ltd","depth":1,"breadcrumb":"text","isActive":true,"baseCurrency":"ZAR","childCount":3}],"rootId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","depth":1},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"PUT","path":"/api/company-hierarchy/{id}/parent","summary":"Re-parent an entity. Refused if it would create a cycle.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","tradeName":"Karoo Fresh Holdings Ltd","companyType":"standard","baseCurrency":"ZAR","isActive":true,"depth":1,"path":"text","childCount":3,"descendantCount":3,"ownershipPercent":15.0,"effectiveOwnershipPercent":15.0,"consolidationMethod":"eft","orphaned":false},"body":{"parentCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","ownershipPercent":15.0,"consolidationMethod":"eft"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/company-hierarchy/repair","summary":"Repair an inconsistent hierarchy — orphans and broken depth values.","auth":"jwt","responseExample":{"companiesScanned":1,"pathsRewritten":1,"cyclicCompanyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"orphanedCompanyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/company-hierarchy/{id}/consolidated/income-statement?from=2026-03-01&to=2027-02-28","summary":"Consolidated income statement at ANY node of the tree, not only the group head. The lines are the figures after eliminations. A foreign subsidiary's income and expenses are translated at the rate of the day each was posted (IFRS for SMEs 30.18); translationNotice names the closing rates used.","auth":"jwt","responseExample":{"scope":{"rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootName":"Karoo Fresh Holdings Ltd","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"companyCount":3,"excluded":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"maxDepth":1},"periodLabel":"2026-09","presentationCurrency":"ZAR","combinedRevenue":1.0,"combinedCostOfSales":10005.0,"combinedOperatingExpenses":1.0,"eliminatedIntercompanyTurnover":1.0,"consolidatedRevenue":1.0,"consolidatedCostOfSales":10005.0,"consolidatedOperatingExpenses":1.0,"consolidatedGrossProfit":1.0,"consolidatedOperatingProfit":1.0,"taxExpense":1305.0,"consolidatedProfitAfterTax":1305.0,"profitAttributableToOwners":1.0,"profitAttributableToNonControlling":1.0,"revenueLines":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"costOfSalesLines":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"operatingExpenseLines":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"nonControllingInterest":{"shareOfProfit":1.0,"shareOfNetAssets":8700.0,"perEntity":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","effectiveOwnershipPercent":15.0,"nonControllingPercent":15.0,"standaloneProfit":1.0,"standaloneNetAssets":8700.0,"nonControllingProfit":1.0,"nonControllingNetAssets":8700.0}],"whollyOwnedGroup":true}},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/company-hierarchy/{id}/consolidated/balance-sheet?asOf=2027-02-28","summary":"Consolidated balance sheet at any node. The lines are the figures after eliminations and add up to the totals. A foreign subsidiary's assets and liabilities are translated at the closing rate of asOf, its equity at historical rates, and the difference is the translation reserve in equity; translationNotice names each closing rate with its date and source.","auth":"jwt","responseExample":{"scope":{"rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootName":"Karoo Fresh Holdings Ltd","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"companyCount":3,"excluded":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"maxDepth":1},"asOfLabel":"Karoo Fresh Holdings Ltd","presentationCurrency":"ZAR","nonCurrentAssets":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"currentAssets":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"nonCurrentLiabilities":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"currentLiabilities":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"equityLines":[{"name":"Karoo Fresh Holdings Ltd","amount":10005.0}],"combinedTotalAssets":10005.0,"combinedTotalLiabilities":10005.0,"eliminatedIntercompanyBalances":10005.0,"consolidatedTotalAssets":10005.0,"consolidatedTotalLiabilities":10005.0,"consolidatedNetAssets":8700.0,"equityAttributableToOwners":1.0,"nonControllingInterestEquity":1.0,"nonControllingInterest":{"shareOfProfit":1.0,"shareOfNetAssets":8700.0,"perEntity":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","effectiveOwnershipPercent":15.0,"nonControllingPercent":15.0,"standaloneProfit":1.0,"standaloneNetAssets":8700.0,"nonControllingProfit":1.0,"nonControllingNetAssets":8700.0}],"whollyOwnedGroup":true},"balancingDifference":1.0,"eliminatedInvestment":60000.0,"eliminatedSubsidiaryCapital":60000.0,"goodwill":0.0,"bargainPurchaseGain":0.0,"investmentNotice":"The investment of R60 000.00 is set against the group's share of the subsidiaries' share capital as their books hold it at this date."},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/company-hierarchy/{id}/consolidated/trial-balance?from=2026-03-01&to=2027-02-28","summary":"Consolidated trial balance at any node. Each row is the figure after eliminations (eliminationDebit and eliminationCredit say how much of it is an elimination) and the foreign currency translation reserve (3550) balances the translated subsidiaries.","auth":"jwt","responseExample":{"scope":{"rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootName":"Karoo Fresh Holdings Ltd","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"companyCount":3,"excluded":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"maxDepth":1},"from":"2026-09-01","to":"2026-09-30","periodLabel":"2026-09","presentationCurrency":"ZAR","rows":[{"code":"CT-001","name":"Karoo Fresh Holdings Ltd","accountType":"asset","openingBalance":10005.0,"debit":1.0,"credit":1.0,"closingBalance":10005.0,"closingDebit":1.0,"closingCredit":1.0,"contributingCompanies":1}],"totalDebit":10005.0,"totalCredit":10005.0,"totalClosingDebit":10005.0,"totalClosingCredit":10005.0,"balanced":true,"empty":true,"eliminations":{"scope":{"rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootName":"Karoo Fresh Holdings Ltd","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"companyCount":3,"excluded":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"maxDepth":1},"eliminated":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromName":"Karoo Fresh Holdings Ltd","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toName":"Karoo Fresh Holdings Ltd","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"open":true}],"external":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromName":"Karoo Fresh Holdings Ltd","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toName":"Karoo Fresh Holdings Ltd","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"open":true}],"eliminatedTurnover":1.0,"eliminatedBalances":10005.0,"externalTurnover":1.0}},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/company-hierarchy/{id}/consolidated/eliminations?from=2026-03-01&to=2027-02-28","summary":"The inter-company eliminations applied, line by line.","auth":"jwt","responseExample":{"scope":{"rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","rootName":"Karoo Fresh Holdings Ltd","companyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"companyCount":3,"excluded":[{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","reason":"Budget deferred to the next financial year."}],"maxDepth":1},"eliminated":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromName":"Karoo Fresh Holdings Ltd","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toName":"Karoo Fresh Holdings Ltd","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"open":true}],"external":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromName":"Karoo Fresh Holdings Ltd","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toName":"Karoo Fresh Holdings Ltd","date":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"open":true}],"eliminatedTurnover":1.0,"eliminatedBalances":10005.0,"externalTurnover":1.0},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/intercompany-transactions?status=open&companyId=3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","summary":"The inter-company transaction log.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"POST","path":"/api/intercompany-transactions","summary":"Record an inter-company transaction. `kind` says what the amount is: trade (a sale or service, the default), loan or dividend. A loan or dividend is a balance between the two companies and is never eliminated as turnover; a sale is eliminated net of VAT. For a sale of goods, `sellerCost` (what the goods cost the seller) and `buyerHeldPercent` (0-100, the share the buyer still holds) let consolidation eliminate the unrealised profit from inventory and group profit. For a sale of equipment, `buyerAssetId` (the asset in the buyer's register) with `sellerCost` (the seller's carrying amount) lets consolidation eliminate the gain and the depreciation charged on it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","kind":"trade"},"body":{"fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-08-31","description":"Management fee","amount":85000.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","kind":"trade","sellerCost":60000.0,"buyerHeldPercent":100.0,"buyerAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/intercompany-transactions/{id}","summary":"One transaction.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"PUT","path":"/api/intercompany-transactions/{id}","summary":"Correct a transaction. Every field is replaced; an eliminated transaction is refused. Omit `kind` to keep the transaction's kind; a transaction that mirrors an invoice or records a bank payment cannot change it.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z","kind":"trade"},"body":{"fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-08-27","description":"Management fee - corrected","amount":90000.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","kind":"trade","sellerCost":60000.0,"buyerHeldPercent":100.0,"buyerAssetId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"DELETE","path":"/api/intercompany-transactions/{id}","summary":"Delete a transaction.","auth":"jwt","responseKind":"none","module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/intercompany-transactions/{id}/match","summary":"Agree both legs of a transaction. PENDING only.","auth":"jwt","responseExample":{"message":"Transaction matched"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/intercompany-transactions/{id}/settle","summary":"Eliminate an inter-company transaction for consolidation. MATCHED only. Wire alias of /{id}/eliminate; it does NOT record that one entity paid another - that is POST /{id}/payment.","auth":"jwt","responseExample":{"message":"Transaction eliminated"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/intercompany-transactions/{id}/eliminate","summary":"Eliminate an inter-company transaction for consolidation. MATCHED only.","auth":"jwt","responseExample":{"message":"Transaction eliminated"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/intercompany-transactions/{id}/payment","summary":"Record that one entity actually paid another. Separate from elimination - an amount is often eliminated and still unpaid.","auth":"jwt","body":{"paidOn":"2026-08-25","reference":"EFT 4471"},"responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"DELETE","path":"/api/intercompany-transactions/{id}/payment","summary":"Remove a payment record. Always permitted, so a mis-keyed settlement is correctable.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","transactionDate":"2026-09-01","description":"Consulting services — August 2026","amount":10005.0,"currency":"ZAR","exchangeRate":1.0,"accountIdFrom":"2026-09-01","accountIdTo":"2026-09-30","status":"PENDING","settledOn":"2026-09-01","settledAt":"2026-09-01T09:15:00Z","settledByName":"Karoo Fresh Holdings Ltd","settlementReference":"INV-0001","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/intercompany-transactions/eliminate-all","summary":"Eliminate every matched transaction for a period in one pass.","auth":"jwt","body":{"period":"2026-08"},"responseExample":{"eliminated":1},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/consolidation-groups","summary":"Consolidation groups and their members.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","baseCurrency":"ZAR","reportingPeriodStart":"2026-09-01","reportingPeriodEnd":"2026-09-30","status":"DRAFT","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"POST","path":"/api/consolidation-groups","summary":"Define a consolidation group.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","baseCurrency":"ZAR","reportingPeriodStart":"2026-09-01","reportingPeriodEnd":"2026-09-30","status":"DRAFT","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"body":{"name":"KMP Group","baseCurrency":"ZAR","reportingPeriodStart":"2026-09-01","reportingPeriodEnd":"2026-09-30","rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/consolidation-groups/{id}","summary":"One group.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","rootCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","baseCurrency":"ZAR","reportingPeriodStart":"2026-09-01","reportingPeriodEnd":"2026-09-30","status":"DRAFT","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"DELETE","path":"/api/consolidation-groups/{id}","summary":"Delete a group.","auth":"jwt","responseKind":"none","module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"POST","path":"/api/consolidation-groups/{id}/run","summary":"Run the consolidation and store the result.","auth":"jwt","body":{"asAt":"2027-02-28"},"responseExample":{"message":"Consolidation finalised","groupId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","eliminationsPosted":1},"module":"multi-company","plan":"Enterprise","scope":"multi-company:write"},{"method":"GET","path":"/api/consolidation-groups/{id}/entries","summary":"The consolidation entries produced by a run.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","groupId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","amount":10005.0,"currency":"ZAR","convertedAmount":10005.0,"exchangeRate":1.0,"entryType":"STANDALONE","createdAt":"2026-09-01T09:15:00Z","updatedAt":"2026-09-01T09:15:00Z"}],"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/multi-company/overview","summary":"Per-entity dashboards — P&L summary, balance sheet and inter-company balances side by side.","auth":"jwt","responseExample":{"financialYearLabel":"Karoo Fresh Holdings Ltd","entities":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","tradeName":"Karoo Fresh Holdings Ltd","registrationNumber":"2021/123456/07","vatNumber":"4123456789","companyType":"standard","baseCurrency":"ZAR","isActive":true,"isParent":true,"parentId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","colorHex":"#0D47A1","icon":"text","financials":{"revenue":1.0,"cogs":1.0,"opex":1.0,"tax":1305.0,"assets":1.0,"liabilities":1.0,"equity":1.0,"cash":1.0,"debtors":1.0,"creditors":1.0},"interCo":{"receivable":1.0,"payable":1.0}}],"totals":{"revenue":1.0,"cogs":1.0,"opex":1.0,"tax":1305.0,"assets":1.0,"liabilities":1.0,"equity":1.0,"cash":1.0,"debtors":1.0,"creditors":1.0,"netProfit":8700.0,"interCoRevenueEliminated":1.0,"interCoExpenseEliminated":1.0,"interCoReceivablesEliminated":1.0,"interCoPayablesEliminated":1.0,"consolidatedRevenue":1.0,"consolidatedAssets":1.0,"consolidatedLiabilities":1.0,"consolidatedNetProfit":8700.0,"pendingIcCount":3}},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/multi-company/ic-matrix","summary":"The cross-entity outstanding balance matrix.","auth":"jwt","responseExample":{"companies":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tradeName":"Karoo Fresh Holdings Ltd","colorHex":"#0D47A1"}],"cells":[{"fromCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","fromTradeName":"Karoo Fresh Holdings Ltd","toCompanyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","toTradeName":"Karoo Fresh Holdings Ltd","pendingAmount":10005.0}]},"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"},{"method":"GET","path":"/api/multi-company/shared-contacts","summary":"Contacts shared across entities, with a per-entity badge.","auth":"jwt","responseExample":[{"name":"Karoo Fresh Holdings Ltd","contactType":"customer","sharedByCompanyIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"],"sharedByTradeNames":["Karoo Fresh Holdings Ltd"]}],"module":"multi-company","plan":"Enterprise","scope":"multi-company:read"}]},{"name":"Accountant workspace","blurb":"The practitioner side of the relationship. A Tax Practitioner role carries full SARS access including export, so an external accountant prepares and downloads every return for the entities they can reach.","endpoints":[{"method":"GET","path":"/api/practitioner/clients","summary":"The client console — every tenant this practitioner is linked to, most in need first: ordered by attentionScore (the sum of attentionWeights, one weight for each line of attentionItems; healthBand is on_track, watch or behind), a tie by client name.","auth":"jwt","responseExample":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","accessLevel":"text","linkedSince":"text","vatRegistered":false,"openQueries":1,"draftJournals":1,"unreconciledTransactions":1,"lastPeriodClosed":false,"lastClosedPeriod":"2026-09","payrollAwaitingPayment":1,"ledgerNotStarted":false,"attentionItems":["text"],"payer":"firm","planId":"compliance","planMonthlyRands":1.0,"addonCentsMonthly":49900}],"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/clients/adjusting-journals","summary":"The console's review queue: the journals entered as drafts and not yet posted in the books of the clients the practice works on (links that show the bookkeeping workload), newest first, each naming its client. count and totalValue are the whole queue; journals is cut at limit. Requires the Practice tier and roles:view.","auth":"jwt","responseExample":{"journals":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"manual","reference":"INV-0001","memo":"text","totalDebit":10005.0,"totalCredit":10005.0,"canOpen":false}],"totalValue":10005.0,"count":1},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/deadlines","summary":"Every SARS deadline across the practice's client book, soonest first — each client company's own deadline list. Requires the Practice tier.","auth":"jwt","responseExample":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","companyName":null,"clientReference":"CUM-01","type":"VAT201","period":"Jul–Aug 2026","dueDate":"2026-09-30","canOpenBooks":false}],"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/links","summary":"Practitioner links and their state.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","practitionerEmail":"accounts@karoofresh.example","practitionerName":"Karoo Fresh Holdings Ltd","status":"sent","accessLevel":"text","invitedAt":"2026-09-01T09:15:00Z","acceptedAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/practitioner/links","summary":"Invite a practitioner, or request access to a client.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","practitionerEmail":"accounts@karoofresh.example","practitionerName":"Karoo Fresh Holdings Ltd","status":"sent","accessLevel":"text","invitedAt":"2026-09-01T09:15:00Z","acceptedAt":"2026-09-01T09:15:00Z"},"body":{"email":"accountant@example.example","name":"Karoo Fresh Holdings Ltd","accessLevel":"full"}},{"method":"PATCH","path":"/api/practitioner/links/{id}","summary":"Change the access a link gives (summary, full or books). A visit open in the books ends at once when books access is withdrawn.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","practitionerEmail":"accounts@karoofresh.example","practitionerName":"Karoo Fresh Holdings Ltd","status":"sent","accessLevel":"text","invitedAt":"2026-09-01T09:15:00Z","acceptedAt":"2026-09-01T09:15:00Z"},"body":{"accessLevel":"books"}},{"method":"DELETE","path":"/api/practitioner/links/{id}","summary":"End a link. Access stops immediately.","auth":"jwt","responseKind":"none"},{"method":"GET","path":"/api/practitioner/invitations","summary":"Invitations waiting on this practitioner.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","practitionerEmail":"accounts@karoofresh.example","practitionerName":"Karoo Fresh Holdings Ltd","status":"invited","accessLevel":"summary","invitedAt":"2026-09-01T09:15:00Z","acceptedAt":"2026-09-01T09:15:00Z","revokedAt":"2026-09-01T09:15:00Z","invitationEmailed":true,"firmName":"Karoo Fresh Holdings Ltd","assignedStaff":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Karoo Fresh Holdings Ltd","email":"accounts@karoofresh.example","roleName":"Karoo Fresh Holdings Ltd","isSelf":false}]}]},{"method":"POST","path":"/api/practitioner/accept/{id}","summary":"Accept an invitation.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","practitionerEmail":"accounts@karoofresh.example","practitionerName":"Karoo Fresh Holdings Ltd","status":"sent","accessLevel":"text","invitedAt":"2026-09-01T09:15:00Z","acceptedAt":"2026-09-01T09:15:00Z"}},{"method":"GET","path":"/api/practitioner/link-requests","summary":"Every request this practice has sent a business to connect, with what became of each. Requires the Practice tier and roles:view.","auth":"jwt","responseExample":[{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","clientEmail":"accounts@karoofresh.example","accessLevel":"books","message":"Following our meeting — please connect us so we can take over the year-end.","status":"waiting","requestedByName":"Thandi van Wyk","requestedByEmail":"thandi@vanwyk.example","createdAt":"2026-09-01T09:15:00Z","expiresAt":"2026-10-01T09:15:00Z"}],"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/link-requests","summary":"Ask a business to connect to this practice. Answers identically whether or not the address belongs to anyone on Ledgr; a repeat to an address already waiting returns that request and sends nothing. Requires the Practice tier and roles:create.","auth":"jwt","body":{"email":"accounts@karoofresh.example","accessLevel":"books","message":"Following our meeting — please connect us so we can take over the year-end."},"responseExample":{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","clientEmail":"accounts@karoofresh.example","accessLevel":"books","message":"Following our meeting — please connect us so we can take over the year-end.","status":"waiting","requestedByName":"Thandi van Wyk","requestedByEmail":"thandi@vanwyk.example","createdAt":"2026-09-01T09:15:00Z","expiresAt":"2026-10-01T09:15:00Z","emailed":true},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/link-requests/{id}/withdraw","summary":"Withdraw a request that is still waiting. Requires the Practice tier and roles:create.","auth":"jwt","responseExample":{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","clientEmail":"accounts@karoofresh.example","accessLevel":"books","status":"withdrawn","requestedByName":"Thandi van Wyk","requestedByEmail":"thandi@vanwyk.example","createdAt":"2026-09-01T09:15:00Z","expiresAt":"2026-10-01T09:15:00Z"},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/connection-requests","summary":"Practices asking this business to connect — addressed to the caller, or to any of the business's people when the caller may answer. Every plan.","auth":"jwt","responseExample":[{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","firmName":"Van Wyk & Associates","requestedByName":"Thandi van Wyk","requestedByEmail":"thandi@vanwyk.example","addressedTo":"accounts@karoofresh.example","accessLevel":"books","message":"Following our meeting — please connect us so we can take over the year-end.","createdAt":"2026-09-01T09:15:00Z","expiresAt":"2026-10-01T09:15:00Z","mayRespond":false}]},{"method":"POST","path":"/api/practitioner/connection-requests/{id}/accept","summary":"Accept a practice's request at the level the business chooses, writing an active accountant link. Requires roles:create, as inviting an accountant does.","auth":"jwt","body":{"accessLevel":"full"},"responseExample":{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","status":"accepted","firmName":"Van Wyk & Associates","linkId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accessLevel":"full","notice":"Van Wyk & Associates is connected with Workload access. You can change or remove it under Settings → Accountant access at any time."}},{"method":"POST","path":"/api/practitioner/connection-requests/{id}/decline","summary":"Decline a practice's request. Nothing is shared. Requires roles:create.","auth":"jwt","responseExample":{"id":"7c2e4f10-9a3b-4d8e-b1f2-5a6c7d8e9f01","status":"declined","firmName":"Van Wyk & Associates","notice":"Declined. Nothing was shared with Van Wyk & Associates."}},{"method":"GET","path":"/api/practitioner/queries?status=open","summary":"In-app queries between practitioner and client, in place of an email thread nobody can find later.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"standard","subjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectLabel":"Karoo Fresh Holdings Ltd","question":"text","status":"sent","priority":"normal","answer":"text","askedByEmail":"accounts@karoofresh.example","createdAt":"2026-09-01T09:15:00Z","answeredAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/api/practitioner/queries","summary":"Raise a query, optionally against a specific transaction (subjectType bank with the line's id as subjectId). The client is emailed once when a practice raises one inside its books, unless it has switched 'Your accountant's questions' off, and reminded while it stays open: after 3 days, then weekly, at most 6 times. A client the practice placed (no user) is sent the address the practice holds for it, with a link that needs no account; a replay of the same clientId tells nobody twice.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"standard","subjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectLabel":"Karoo Fresh Holdings Ltd","question":"text","status":"sent","priority":"normal","answer":"text","askedByEmail":"accounts@karoofresh.example","createdAt":"2026-09-01T09:15:00Z","answeredAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z"},"body":{"question":"Please send the September bank statement.","subjectType":"general","subjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectLabel":"Karoo Fresh Holdings Ltd","priority":"normal","clientId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"question","dueDate":"2026-09-01"}},{"method":"POST","path":"/api/practitioner/queries/{id}/answer","summary":"Answer a query.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"standard","subjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectLabel":"Karoo Fresh Holdings Ltd","question":"text","status":"sent","priority":"normal","answer":"text","askedByEmail":"accounts@karoofresh.example","createdAt":"2026-09-01T09:15:00Z","answeredAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z"},"body":{"answer":"Attached — the September statement."}},{"method":"POST","path":"/api/practitioner/queries/{id}/resolve","summary":"Close a query.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"standard","subjectId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectLabel":"Karoo Fresh Holdings Ltd","question":"text","status":"sent","priority":"normal","answer":"text","askedByEmail":"accounts@karoofresh.example","createdAt":"2026-09-01T09:15:00Z","answeredAt":"2026-09-01T09:15:00Z","resolvedAt":"2026-09-01T09:15:00Z"}},{"method":"GET","path":"/api/practitioner/adjusting-journals","summary":"Adjusting journals waiting on the client's review.","auth":"jwt","responseExample":{"journals":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","journalNumber":"INV-0001","journalDate":"2026-09-01","sourceType":"invoice","sourceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","reference":"INV-0001","memo":"text","status":"sent","totalDebit":10005.0,"totalCredit":10005.0,"reversedBy":"text","reverses":"text","lines":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","accountCode":"CT-001","accountName":"Karoo Fresh Holdings Ltd","description":"Consulting services — August 2026","debit":1.0,"credit":1.0,"costCentreId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"}],"editable":false}],"totalValue":10005.0,"count":3}},{"method":"POST","path":"/api/practitioner/clients","summary":"Place a Compliance client the practice pays for. Requires the Practice tier and roles:create.","auth":"jwt","requestExample":{"name":"Dormant Holdings","reference":"DH-01"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","reference":"INV-0001","planId":"compliance","linkId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","notice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/clients/{id}/session","summary":"Open a client's books. Returns a short-lived access-only token scoped to that tenant; the client's own live link is the authority, so no permission in the practice's tenant is read.","auth":"jwt","responseExample":{"accessToken":"<never returned>","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","expiresInMinutes":1,"notice":"This run includes a catch-up deduction; the year-to-date total is correct.","placedByPractice":false},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/clients/{id}/billing","summary":"Take over a client's subscription, or hand it back. Requires roles:edit.","auth":"jwt","requestExample":{"payer":"firm"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","payer":"firm","clientNotice":"This run includes a catch-up deduction; the year-to-date total is correct.","chargedCentsMonthly":49900,"proratedCentsNow":49900},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/bulk-run","summary":"Run one named action for up to 100 clients at once: vat201-check (what to look at before the VAT201 is filed), vat201-draft (prepare the VAT201 draft, never filed) or emp201-check (last month's EMP201 and what stops it being filed). Each client is entered through the same gate a visit uses and held to its own role and plan, so a client that refuses is refused alone, in its own words, and the others are run. Answers one outcome per client, in the order asked. Requires the Practice tier and roles:edit.","auth":"jwt","requestExample":{"action":"vat201-check","clientIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"action":"vat201-check","actionTitle":"Check the VAT201 before filing","summary":"1 client: 1 done.","outcomes":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","status":"done","message":"VAT201 for 1 Oct 2026 to 31 Oct 2026: nothing to flag before filing."}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/report-templates","summary":"The practice's report templates, newest first: each a name and the checks (bulk-run actions) it runs, in order. promise is the one sentence that states what applying one does. Requires the Practice tier and roles:view.","auth":"jwt","responseExample":{"templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Month end","actionIds":["vat201-check","emp201-check"],"summary":"Check the VAT201 before filing, then check last month's EMP201","createdAt":"2026-11-01T09:15:00Z"}],"promise":"A template runs the checks you chose, in that order, for the clients you tick - each under that client's own access. It reads, or prepares a draft. It never files anything."},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/report-templates","summary":"Keep a named set of checks (vat201-check, vat201-draft, emp201-check), each at most once, in the order given. Refused when the name is blank, over 60 characters or already used, when no check or an unknown or repeated one is chosen, or past 50 templates. Requires the Practice tier and roles:edit.","auth":"jwt","requestExample":{"name":"Month end","actionIds":["vat201-check","emp201-check"]},"responseExample":{"templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Month end","actionIds":["vat201-check","emp201-check"],"summary":"Check the VAT201 before filing, then check last month's EMP201","createdAt":"2026-11-01T09:15:00Z"}],"promise":"A template runs the checks you chose, in that order, for the clients you tick - each under that client's own access. It reads, or prepares a draft. It never files anything."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/report-templates/{id}/apply","summary":"Apply a template to up to 100 clients: each check in it runs in order as bulk-run runs it (the same gate into each client, the client's own role and plan, one outcome per client), and the answer carries one run per check. Never files anything. Requires the Practice tier and roles:edit.","auth":"jwt","requestExample":{"clientIds":["3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"]},"responseExample":{"templateName":"Month end","runs":[{"action":"vat201-check","actionTitle":"Check the VAT201 before filing","summary":"1 client: 1 done.","outcomes":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","status":"done","message":"VAT201 for 1 Oct 2026 to 31 Oct 2026: nothing to flag before filing."}]}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"DELETE","path":"/api/practitioner/report-templates/{id}","summary":"Retire one of the practice's report templates. Nothing it already ran is touched. Requires the Practice tier and roles:edit.","auth":"jwt","responseExample":{"templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Month end","actionIds":["vat201-check","emp201-check"],"summary":"Check the VAT201 before filing, then check last month's EMP201","createdAt":"2026-11-01T09:15:00Z"}],"promise":"A template runs the checks you chose, in that order, for the clients you tick - each under that client's own access. It reads, or prepares a draft. It never files anything."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/clients/{id}/addons","summary":"What this practice can turn on for one client, and what it costs the practice. Requires roles:view.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","planId":"business","planDisplayName":"Karoo Fresh Holdings Ltd","payer":"firm","blocker":"text","held":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":1,"unitLabel":"Karoo Fresh Holdings Ltd","requiresNote":"Budget deferred to the next financial year.","proRataCents":49900,"proRataNote":"Budget deferred to the next financial year.","pendingOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","pendingCheckoutUrl":"https://app.ledgrsa.com/pay/3f1a7c92","pendingAmountCents":49900}],"available":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","displayName":"Karoo Fresh Holdings Ltd","blurb":"Budget deferred to the next financial year.","unitPriceMonthly":2900.0,"quantity":3,"monthlyPrice":10005.0,"seatsPerUnit":1,"unlocks":["text"],"maxQuantity":1,"unitLabel":"Karoo Fresh Holdings Ltd","requiresNote":"Budget deferred to the next financial year.","proRataCents":49900,"proRataNote":"Budget deferred to the next financial year.","pendingOrderId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","pendingCheckoutUrl":"https://app.ledgrsa.com/pay/3f1a7c92","pendingAmountCents":49900}],"addonCentsMonthly":49900},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/clients/{id}/addons","summary":"The practice agreeing to an add-on for a client it pays for. Granted at once and charged on the practice's next consolidated cycle. Requires roles:edit.","auth":"jwt","requestExample":{"addonId":"logistics","quantity":1},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","addonId":"job-cards","quantity":3,"addonCentsMonthly":49900,"proratedCentsNow":49900,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"DELETE","path":"/api/practitioner/clients/{id}/addons/{addonId}","summary":"The practice taking an add-on off a client, and off its own next bill. Requires roles:edit.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","addonId":"job-cards","quantity":3,"addonCentsMonthly":49900,"proratedCentsNow":49900,"notice":"This run includes a catch-up deduction; the year-to-date total is correct."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/clients/{id}/tax-references","summary":"The SARS references on the holding company of a client the firm PLACED — VAT number and category, income tax, PAYE, UIF and SDL. A client that runs its own account answers 409 with the sentence telling the firm to ask the client to add them under Settings → Company. Requires roles:view.","auth":"jwt","responseExample":{"vatNumber":"4123456789","vatCategory":"B","taxNumber":"9123456789","payeNumber":"7123456789","uifNumber":"U123456789","sdlNumber":"L123456789"},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"PUT","path":"/api/practitioner/clients/{id}/tax-references","summary":"Set a placed client's tax references, judged by the company profile's own rules. Null keeps a reference, blank clears it. Audited in the firm's trail and the client's. Refused (409) for a client that runs its own account. Requires roles:edit.","auth":"jwt","requestExample":{"vatNumber":"4123456789","vatCategory":"B","taxNumber":"9123456789","payeNumber":"7123456789","uifNumber":"U123456789","sdlNumber":"L123456789"},"responseExample":{"vatNumber":"4123456789","vatCategory":"B","taxNumber":"9123456789","payeNumber":"7123456789","uifNumber":"U123456789","sdlNumber":"L123456789"},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/visit/filing-profile","summary":"From a books visit: the visited company's VAT category and financial year end, the two settings that set when its returns are due. Answers 403 to anyone who is not a practice's visit. Requires sars:view.","auth":"jwt","responseExample":{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyName":"Sibanda Plumbing","vatCategory":"B","fiscalYearEndMonth":2,"fiscalYearEndName":"February"}},{"method":"PUT","path":"/api/practitioner/visit/filing-profile","summary":"From a books visit: correct the visited company's VAT category (A to F, or NONE), its financial year end (1 to 12), or both. Null leaves a setting alone; a blank category clears it. The numbers (VAT, PAYE, UIF, SDL, income tax) are not changed here. Judged by the rules Settings → Company uses, written to the same columns, and audited in the client's trail at warning with what changed and from what. Answers 403 to anyone who is not a practice's visit. Requires sars:approve.","auth":"jwt","requestExample":{"vatCategory":"B","fiscalYearEndMonth":6},"responseExample":{"companyId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","companyName":"Sibanda Plumbing","vatCategory":"B","fiscalYearEndMonth":6,"fiscalYearEndName":"June"}},{"method":"GET","path":"/api/practitioner/clients/{id}/fields","summary":"The practice's own fields on one client — definitions and this client's answers in one call. The client is never shown these. Requires roles:view.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","summary":"Partner: AC · Cycle: Monthly","fields":[{"fieldId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","name":"Partner","kind":"text","value":"AC","display":"AC"},{"fieldId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Cycle","kind":"text","value":"Monthly","display":"Monthly"}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/clients/{id}/fields","summary":"Define a new field for the whole practice. It appears on every client, empty. Requires roles:edit.","auth":"jwt","requestExample":{"name":"Partner","kind":"text"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","summary":"Partner: AC · Cycle: Monthly","fields":[{"fieldId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","name":"Partner","kind":"text","value":"AC","display":"AC"},{"fieldId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Cycle","kind":"text","value":"Monthly","display":"Monthly"}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"PUT","path":"/api/practitioner/clients/{id}/fields/{fieldId}","summary":"Set or clear this client's answer. A blank value clears it and is not an error. Requires roles:edit.","auth":"jwt","requestExample":{"value":"AC"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","summary":"Partner: AC · Cycle: Monthly","fields":[{"fieldId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","name":"Partner","kind":"text","value":"AC","display":"AC"},{"fieldId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Cycle","kind":"text","value":"Monthly","display":"Monthly"}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"PUT","path":"/api/practitioner/clients/{id}/fields/{fieldId}/name","summary":"Rename the field for the whole practice, keeping every client's answer. Requires roles:edit.","auth":"jwt","requestExample":{"name":"Engagement partner"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","summary":"Partner: AC · Cycle: Monthly","fields":[{"fieldId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","name":"Partner","kind":"text","value":"AC","display":"AC"},{"fieldId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Cycle","kind":"text","value":"Monthly","display":"Monthly"}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"DELETE","path":"/api/practitioner/clients/{id}/fields/{fieldId}","summary":"Retire the field. Soft — it leaves the panel and every client's answer is kept. Requires roles:edit.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","summary":"Partner: AC · Cycle: Monthly","fields":[{"fieldId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","name":"Partner","kind":"text","value":"AC","display":"AC"},{"fieldId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Cycle","kind":"text","value":"Monthly","display":"Monthly"}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/clients/{id}/staff","summary":"Who at the practice is on one client, who else could be, and the sentence the client is shown about it. Requires roles:view.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","inviteeEmail":"thabo@mokoenapartners.example","inviteeName":"Thabo Nkosi","assigned":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"roster":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"clientIsTold":"Mokoena Partners has also assigned Ayesha Patel to your books. They work under the same access you granted, for fifteen minutes at a time, and everything each of them does is recorded against their own name in your audit trail."},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/clients/{id}/staff","summary":"Assign a colleague at the practice to a client. The person the client invited by name already holds the grant and is refused. Requires roles:edit.","auth":"jwt","requestExample":{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03"},"responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","inviteeEmail":"thabo@mokoenapartners.example","inviteeName":"Thabo Nkosi","assigned":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"roster":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"clientIsTold":"Mokoena Partners has also assigned Ayesha Patel to your books. They work under the same access you granted, for fifteen minutes at a time, and everything each of them does is recorded against their own name in your audit trail."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"DELETE","path":"/api/practitioner/clients/{id}/staff/{userId}","summary":"Take a colleague off a client. The person the client invited cannot be removed here — only the client can. Requires roles:edit.","auth":"jwt","responseExample":{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","inviteeEmail":"thabo@mokoenapartners.example","inviteeName":"Thabo Nkosi","assigned":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"roster":[{"userId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Ayesha Patel","email":"ayesha@mokoenapartners.example","roleName":"Accountant","isSelf":false}],"clientIsTold":"Mokoena Partners has also assigned Ayesha Patel to your books. They work under the same access you granted, for fifteen minutes at a time, and everything each of them does is recorded against their own name in your audit trail."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/time","summary":"The firm's time across its whole client book, with what is unbilled per client. These are Time Tracking hours logged on Workflows cards that name a client — no separate timesheet. Money is in CENTS. Requires roles:view.","auth":"jwt","responseExample":{"summary":"R 3 325.00 unbilled across 2 clients","nonBillableNote":"0.75 hours are marked non-billable","unbilledCents":332500,"notice":null,"clients":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","hours":2.75,"nonBillableHours":0.75,"unbilledHours":2.0,"unbilledCents":190000,"billedCents":0,"lastWorkedOn":"2026-09-19"}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/engagements","summary":"What every client has agreed to, and for what fees. A letter is a quote on the contact that represents the client, so it is sent, signed and filed by the ordinary Invoicing and customer-portal path. Money is in CENTS. Requires roles:view.","auth":"jwt","responseExample":{"summary":"1 of 2 clients have signed · 1 waiting on the client","notice":null,"clients":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","documentId":"6c2d51ae-90b7-4c33-8a52-7d1f4e0b93c5","documentNumber":"QUO-2026-014","status":"accepted","statusWord":"Signed","feeCents":1955000,"issuedOn":"2026-09-19","decidedOn":"2026-09-21","signedByName":"Thandi Nkosi","declineReason":null,"services":["Annual financial statements","Company income tax return (ITR14)"]}],"services":[{"id":"afs","name":"Annual financial statements","suggestedFee":12500.0,"scope":"We compile your annual financial statements for each financial year from the records you keep in Ledgr, and we discuss them with you before they are signed."}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/clients/{id}/engagement/schedules","summary":"Set up the client's ACCEPTED engagement letter's monthly fee lines (those that say per month) as recurring invoices in the practice's own invoicing: monthly, from the first of next month, each cycle left as a draft. Idempotent - a line already set up is found, not made again; the annual and once-off lines are left alone. Refused when the letter is not accepted or has no monthly fee. Answers what was done and the whole engagement view again. Requires invoices:create.","auth":"jwt","responseExample":{"notice":"Set up a recurring invoice. Find it under Invoicing, Recurring.","created":1,"alreadyThere":0,"view":{"clients":[],"summary":"No clients to engage yet","services":[]}},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/clients/{id}/engagement","summary":"Write one client's engagement letter from the chosen services, filled in with their name and the fees. Leaves it a DRAFT: sending it is POST /api/invoices/{id}/send, and the client signs by typing their name on the portal link. Refused while an unanswered letter is already out. Requires roles:edit.","auth":"jwt","requestExample":{"serviceIds":["afs","itr14"],"fees":[12500.0,4500.0],"periodDescription":"the year ending 28 February 2027"},"responseExample":{"summary":"1 of 2 clients have signed · 1 waiting on the client","clients":[]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/jobs?offset=0","summary":"What is outstanding across the whole client book, soonest due first. These are Workflows cards that name a client, not a separate job system. One page of 200 from offset; total, summary and overdueNote count the whole queue, and pageNote says which part this is. Requires roles:view.","auth":"jwt","responseExample":{"summary":"12 open across 2 clients","overdueNote":"3 are past their due date","jobs":[{"itemId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","title":"EMP201 · Sept 2026","boardId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","boardName":"Compliance","columnName":"In progress","stage":"in_progress","priority":"high","dueDate":"2026-10-07","overdue":false,"assigneeName":"Ayesha Patel"}],"boards":[{"boardId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Compliance"}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/franchise/links","summary":"The franchisors this business lets read its reports, and invitations still waiting. explains says what a franchisor can and cannot see. Requires roles:view.","auth":"jwt","responseExample":{"links":[{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","franchisorEmail":"finance@kotaking.example","franchisorName":"Head office","status":"active","statusLabel":"Reading your reports","invitedAt":"2026-10-01T08:00:00Z","acceptedAt":"2026-10-01T09:12:00Z"}],"explains":"Your franchisor sees your income statement for any period they choose, read from your books when they ask. They cannot open your books, change anything, or see a single transaction, and nothing of yours is copied into their books. Remove their access here at any time."}},{"method":"POST","path":"/api/franchise/links","summary":"Let a franchisor read this business's income statement: an invitation to their email, which they accept from their own Ledgr business. Read-only; it opens no session in your books and copies nothing into theirs. Requires roles:create.","auth":"jwt","body":{"email":"finance@kotaking.example","name":"Head office"},"responseExample":{"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","franchisorEmail":"finance@kotaking.example","franchisorName":"Head office","status":"invited","statusLabel":"Invited — waiting for them to accept","invitedAt":"2026-10-01T08:00:00Z"}},{"method":"DELETE","path":"/api/franchise/links/{id}","summary":"Remove a franchisor's access at once; their next read is refused. Only the business that granted it can remove it. Requires roles:delete.","auth":"jwt","responseKind":"none"},{"method":"GET","path":"/api/franchise/units","summary":"The franchisor's side: the franchisees sharing their reports with this business, and invitations sent to your email to accept. Requires reports:view.","auth":"jwt","responseExample":{"units":[{"linkId":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","franchiseeName":"Kota King Soweto","status":"active","invitedAt":"2026-10-01T08:00:00Z","acceptedAt":"2026-10-01T09:12:00Z"}],"invitations":[]}},{"method":"POST","path":"/api/franchise/units/{id}/accept","summary":"Accept a franchisee's invitation sent to your own email. Requires reports:view.","auth":"jwt","responseExample":{"linkId":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","franchiseeName":"Kota King Soweto","status":"active","invitedAt":"2026-10-01T08:00:00Z","acceptedAt":"2026-10-01T09:12:00Z"}},{"method":"GET","path":"/api/franchise/units/{id}/report?from=2026-09-01&to=2026-09-30","summary":"One franchisee's income statement for the period, one per company it keeps books for, read from its own ledger when you ask. Nothing is written into your books; the read is recorded in the franchisee's audit log. 404 once the franchisee removes your access. Requires reports:view.","auth":"jwt","responseExample":{"linkId":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","franchiseeName":"Kota King Soweto","from":"2026-09-01","to":"2026-09-30","companies":[{"companyId":"2e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b","companyName":"Kota King Soweto (Pty) Ltd","statement":{"periodLabel":"1 September 2026 – 30 September 2026","revenue":[{"name":"Sales","amount":184500.0,"accountId":"4f1c2b3a-1d2e-4c5b-8a9f-0e1d2c3b4a59"}],"costOfSales":[{"name":"Cost of sales","amount":92250.0,"accountId":"5a2b3c4d-5e6f-4a1b-9c8d-7e6f5a4b3c2d"}],"operatingExpenses":[{"name":"Rent","amount":28000.0,"accountId":"6b3c4d5e-6f7a-4b2c-8d9e-0f1a2b3c4d5e"}],"otherIncome":[],"tax":0.0}}],"readOnly":"Read from the franchisee's own books when you asked. It is not in your books and does not change them."}},{"method":"POST","path":"/api/practitioner/clients/{id}/jobs","summary":"Raise work against one client on one of the practice's own boards. Raising the same title twice names the existing card instead of creating a second one. Requires roles:edit.","auth":"jwt","requestExample":{"boardId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","title":"EMP201 · Sept 2026","dueDate":"2026-10-07","priority":"high"},"responseExample":{"summary":"1 open for one client","overdueNote":null,"jobs":[{"itemId":"8d21b6e0-77c4-4a15-9f30-1b5e9c2a7d64","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Acme Trading (Pty) Ltd","title":"EMP201 · Sept 2026","boardId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","boardName":"Compliance","columnName":"To do","stage":"todo","priority":"high","dueDate":"2026-10-07","overdue":false,"assigneeName":null}],"boards":[{"boardId":"b41f0c93-2ad8-4e77-8c16-5f9e3d0a2b18","name":"Compliance"}],"notice":"\"EMP201 · Sept 2026\" is already on Compliance."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/billing","summary":"The practice's consolidated bill — one line per client it pays for, on one monthly charge.","auth":"jwt","responseExample":{"lines":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Karoo Fresh Holdings Ltd","planId":"business","planDisplayName":"Business","listCentsMonthly":49900,"chargedCentsMonthly":49900,"addons":[{"addonId":"logistics","addonName":"Logistics & Fleet","quantity":1,"centsMonthly":39900}],"totalCentsMonthly":89800}],"totalCentsMonthly":89800,"nextChargeOn":"2026-09-01","currentPeriodEnd":"2026-09-30","status":"active","summary":"Consulting services — August 2026"},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/payouts/statement?from=2026-10-01&to=2026-10-31","summary":"The practice's payout statement for a period, as a PDF: each payout accrued in it — the client, the plan and term, what Ledgr collected, the rung's rate and the payout — with reversals after a client's plan change on their own lines, and what is still owed. Defaults to last calendar month.","auth":"jwt","responseKind":"pdf","module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/payouts","summary":"This firm's own payout ledger: lifetime earned, lifetime paid, and what is still owed.","auth":"jwt","responseExample":{"earnedCentsLifetime":49900,"paidCentsLifetime":49900,"outstandingCents":49900},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"GET","path":"/api/practitioner/payout-bank-details","summary":"The account Ledgr pays this firm's accrued payout into. The account number comes back masked.","auth":"jwt","responseExample":{"configured":false,"bankName":"FNB","accountHolder":"text","accountNumberMasked":"62012345678","branchCode":"250655"},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"PUT","path":"/api/practitioner/payout-bank-details","summary":"Set or replace where Ledgr pays this firm's payout. Decides which bank account receives real money, so it needs roles:edit.","auth":"jwt","body":{"bankName":"FNB","accountHolder":"Example Accounting Inc","accountNumber":"62012345678","branchCode":"250655"},"responseExample":{"configured":true,"bankName":"FNB","accountHolder":"text","accountNumberMasked":"62012345678","branchCode":"250655"},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/directory-listing","summary":"This firm's entry in the public find-an-accountant directory, whether it is shown, and — when Ledgr has hidden it — why.","auth":"jwt","responseExample":{"exists":false,"optedIn":false,"displayName":"Karoo Fresh Holdings Ltd","town":"text","province":"Western Cape","services":["text"],"contactEmail":"accounts@karoofresh.example","website":"https://app.ledgrsa.com/pay/3f1a7c92","hidden":false,"hiddenReason":"Budget deferred to the next financial year.","listed":false,"eligible":false,"summary":"Consulting services — August 2026"},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"PUT","path":"/api/practitioner/directory-listing","summary":"Set or replace this firm's directory listing, the opt-in included. Only a partner practice may hold one. Nothing is published until optedIn is true, and re-saving never clears a hide Ledgr applied.","auth":"jwt","body":{"optedIn":true,"displayName":"Mokoena & Associates","town":"Polokwane","province":"limpopo","services":["tax","vat","payroll"],"contactEmail":"hello@mokoena.example","website":"https://mokoena.example"},"responseExample":{"exists":false,"optedIn":false,"displayName":"Karoo Fresh Holdings Ltd","town":"text","province":"Western Cape","services":["text"],"contactEmail":"accounts@karoofresh.example","website":"https://app.ledgrsa.com/pay/3f1a7c92","hidden":false,"hiddenReason":"Budget deferred to the next financial year.","listed":false,"eligible":false,"summary":"Consulting services — August 2026"},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/professional-registration","summary":"This firm's professional-body registration, and what its payout rate is being held at until Ledgr has checked it.","auth":"jwt","responseExample":{"status":"submitted","body":"saica","bodyLabel":"SAICA","membershipNumber":"20012345","decisionNote":null,"submittedAt":"2026-09-01T09:15:00Z","decidedAt":null,"payoutHeld":true,"rungLabel":"Bronze","rungPercent":15.0,"summary":"text"},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"PUT","path":"/api/practitioner/professional-registration","summary":"Submit or correct this firm's body and membership number. A firm cannot verify itself — the only status this produces is submitted.","auth":"jwt","body":{"body":"saica","membershipNumber":"20012345"},"responseExample":{"status":"submitted","body":"saica","bodyLabel":"SAICA","membershipNumber":"20012345","decisionNote":null,"submittedAt":"2026-09-01T09:15:00Z","decidedAt":null,"payoutHeld":true,"rungLabel":"Bronze","rungPercent":15.0,"summary":"text"},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/account-templates","summary":"The firm's standard charts of accounts, each captured from one client and applicable to any other. `promise` is the single sentence that states what applying one does, so the console, the confirmation and any help page cannot disagree.","auth":"jwt","responseExample":{"promise":"Applying a template only ADDS accounts. It never renames, moves or removes anything the client already has, so it is safe on a client with a full set of books.","templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Restaurants","lineCount":12,"sourceName":"Thabo Restaurants","capturedAt":"2026-09-01T09:15:00Z","summary":"12 accounts on top of the standard chart · from Thabo Restaurants · 2026-09-01","lines":[{"code":"6410","name":"Kitchen consumables","accountType":"expense","normalBalance":"debit","accountSubtype":"operating_expense","parentCode":"6400","cashFlowSection":"operating","isContra":false}]}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"POST","path":"/api/practitioner/account-templates","summary":"Keep one client's chart of accounts as a named template. Refused when the client has nothing beyond the standard chart, when the name is already in use, or past the ceilings (100 templates, 500 accounts) — never silently truncated.","auth":"jwt","responseExample":{"promise":"Applying a template only ADDS accounts. It never renames, moves or removes anything the client already has, so it is safe on a client with a full set of books.","templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Restaurants","lineCount":12,"sourceName":"Thabo Restaurants","capturedAt":"2026-09-01T09:15:00Z","summary":"12 accounts on top of the standard chart · from Thabo Restaurants · 2026-09-01","lines":[{"code":"6410","name":"Kitchen consumables","accountType":"expense","normalBalance":"debit","accountSubtype":"operating_expense","parentCode":"6400","cashFlowSection":"operating","isContra":false}]}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/account-templates/{templateId}/apply/{clientId}?companyId=6b7f6d0e-3a52-4c1e-8a54-0c4f5f6a7b01","summary":"Install a template into a client's chart, into its holding company or, with `?companyId=`, into one of the client's other companies (another client's company is not found). It can only ADD: a code the client already holds — live OR deleted — is skipped and reported by name, never renamed, re-parented, re-typed or revived. `skipped` is the safety rule working, not a partial failure.","auth":"jwt","responseExample":{"added":["6410","6420"],"skipped":[{"code":"6400","name":"Kitchen costs","reason":"the client already has this code"}],"notice":"Added 2 accounts · left 1 account alone because the client already has those codes."},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"GET","path":"/api/practitioner/clients/{id}/companies","summary":"The companies of a linked client, the holding company first, so a template can be installed into the one that needs it (`POST .../apply/{clientId}?companyId=`). Requires roles:view.","auth":"jwt","responseExample":{"companies":[{"id":"6b7f6d0e-3a52-4c1e-8a54-0c4f5f6a7b01","name":"Naidoo Eatery"},{"id":"9d1c2e44-7b10-4f6a-b2a7-5a3c8d0e1f22","name":"Naidoo Catering"}]},"module":"practice","plan":"Practice","scope":"practice:read"},{"method":"DELETE","path":"/api/practitioner/account-templates/{templateId}","summary":"Retire one of the firm's templates. Nothing already applied to a client is touched — an applied template leaves accounts, not a link.","auth":"jwt","responseExample":{"promise":"Applying a template only ADDS accounts. It never renames, moves or removes anything the client already has, so it is safe on a client with a full set of books.","templates":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","name":"Restaurants","lineCount":12,"sourceName":"Thabo Restaurants","capturedAt":"2026-09-01T09:15:00Z","summary":"12 accounts on top of the standard chart · from Thabo Restaurants · 2026-09-01","lines":[{"code":"6410","name":"Kitchen consumables","accountType":"expense","normalBalance":"debit","accountSubtype":"operating_expense","parentCode":"6400","cashFlowSection":"operating","isContra":false}]}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/clients/{id}/invoice","summary":"Raise the firm's own invoice to one client from its approved, unbilled hours, grouped by the work and the rate each hour was captured at. Every entry billed is stamped with the invoice in the same transaction, so a second call finds nothing to bill rather than billing twice.","auth":"jwt","responseExample":{"summary":"R 1 425.00 unbilled across 1 client","notice":"Invoice INV-2026-014 raised for 2 hours, R 1 900.00. Those entries are now billed.","unbilledCents":142500,"clients":[{"clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Naidoo Logistics Prof","hours":1.5,"unbilledHours":1.5,"unbilledCents":142500,"readyToBillHours":1.5,"readyToBillCents":142500,"awaitingApprovalHours":0.0,"awaitingApprovalCents":0,"billedCents":0,"lastWorkedOn":"2026-09-01"}]},"module":"practice","plan":"Practice","scope":"practice:write"},{"method":"POST","path":"/api/practitioner/queries/{id}/files?filename=SignedPO-4417.pdf&caption=Serial%20plate%20before%20fitting&contentType=application%2Fpdf","summary":"Answer a document request by sending a file. Refused on a QUESTION — a firm that asked \"which account is this?\" and got back a PDF has an answer nobody will read — and the remedy is named rather than implied.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"general","subjectLabel":"February 2026","question":"Please send the February bank statement and the vehicle finance agreement.","kind":"documents","dueDate":"2026-09-30","status":"answered","statusWord":"Answered — 1 sent","clientNote":"Your accountant asked for these by 30 September 2026.","fileCount":1,"priority":"normal","askedByEmail":"owner.prac@ledgraudit.test","createdAt":"2026-09-01T09:15:00Z","files":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"february-bank-statement.pdf","caption":"February statement","contentType":"application/pdf","sizeBytes":184320,"uploadedAt":"2026-09-01T09:15:00Z","uploadedByName":"Thandi Nkosi","url":"https://storage.example/ledgr/signed/february-bank-statement.pdf"}]}},{"method":"GET","path":"/api/practitioner/queries/{id}/files","summary":"One request and everything sent against it, each file with a signed, time-limited URL. A request is ANSWERED by a file arriving, which is why `statusWord` and `fileCount` are served rather than recomputed by either screen.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","subjectType":"general","subjectLabel":"February 2026","question":"Please send the February bank statement and the vehicle finance agreement.","kind":"documents","dueDate":"2026-09-30","status":"answered","statusWord":"Answered — 1 sent","clientNote":"Your accountant asked for these by 30 September 2026.","fileCount":1,"priority":"normal","askedByEmail":"owner.prac@ledgraudit.test","createdAt":"2026-09-01T09:15:00Z","files":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","filename":"february-bank-statement.pdf","caption":"February statement","contentType":"application/pdf","sizeBytes":184320,"uploadedAt":"2026-09-01T09:15:00Z","uploadedByName":"Thandi Nkosi","url":"https://storage.example/ledgr/signed/february-bank-statement.pdf"}]}},{"method":"GET","path":"/api/practitioner/document-requests","summary":"The firm's chase list: every document request its own people raised, across the whole client book, with what has arrived. Separate from /api/practitioner/queries because a request lives in the CLIENT's tenant — that endpoint answers a firm with its own queries. Scoped by the ASKER, not by the link, so two firms serving one client never see each other's requests.","auth":"jwt","responseExample":{"summary":"2 of 2 still open · 1 past the date","notice":null,"requests":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Naidoo Logistics Prof","question":"Please send the February bank statement.","dueDate":"2026-09-10","fileCount":0,"statusWord":"Overdue","outstanding":true,"overdue":false,"askedByEmail":"owner.prac@ledgraudit.test","createdAt":"2026-09-01T09:15:00Z"},{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientTenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","clientName":"Thabo Holdings Group","question":"The vehicle finance agreement, please.","dueDate":null,"fileCount":1,"statusWord":"1 sent","outstanding":true,"overdue":false,"askedByEmail":"owner.prac@ledgraudit.test","createdAt":"2026-09-02T07:00:00Z"}]},"module":"practice","plan":"Practice","scope":"practice:read"}]},{"name":"WhatsApp","blurb":"Receipts, reminders, payslips and statements over the WhatsApp Business API. An unconfigured channel fails silently per send, which is why /diagnostics reports whether it is configured at all.","endpoints":[{"method":"GET","path":"/api/whatsapp/config","summary":"Whether WhatsApp is configured, and which templates are approved.","auth":"jwt","responseExample":{"configured":false,"enabled":true,"sending":false,"reason":"Budget deferred to the next financial year."}},{"method":"GET","path":"/api/whatsapp/receipt-senders","summary":"The phones you have linked to send receipts by WhatsApp, a code waiting to be sent, and Ledgr's number.","auth":"jwt","responseExample":{"ledgrNumber":"+27 87 000 0000","onPlan":true,"refusal":null,"linked":[{"id":"7d4f0c1e-2b8a-4f3e-9c55-0f7d2e1a6b90","numberEnding":"4567","linkedAt":"2026-10-12T10:15:00Z"}],"pending":null}},{"method":"POST","path":"/api/whatsapp/receipt-senders","summary":"Start linking your phone: a code to send FROM it to Ledgr's number. The phone is linked when the code arrives.","auth":"jwt","responseExample":{"code":"482913","message":"LINK 482913","ledgrNumber":"+27 87 000 0000","expiresAt":"2026-10-12T10:45:00Z"}},{"method":"DELETE","path":"/api/whatsapp/receipt-senders/{id}","summary":"Unlink one of your phones; what it sends afterwards is dropped.","auth":"jwt","responseKind":"none"},{"method":"PUT","path":"/api/whatsapp/config","summary":"Set the tenant's WhatsApp configuration.","auth":"jwt","body":{"enabled":true,"senderDisplayName":"Your Business"},"responseKind":"json"},{"method":"GET","path":"/api/whatsapp/messages","summary":"Messages sent and their delivery state.","auth":"jwt","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","to":"2026-09-30","templateName":"Karoo Fresh Holdings Ltd","status":"sent","createdAt":"2026-09-01T09:15:00Z"}]},{"method":"GET","path":"/api/whatsapp/messages/{id}","summary":"One message.","auth":"jwt","responseKind":"json"},{"method":"POST","path":"/api/whatsapp/send","summary":"Send a message against an approved template.","auth":"jwt","responseExample":{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","to":"2026-09-30","templateName":"Karoo Fresh Holdings Ltd","status":"sent","createdAt":"2026-09-01T09:15:00Z"},"body":{"to":"2026-09-30","templateName":"Karoo Fresh Holdings Ltd","templateParams":{"1":"Karoo Fresh Holdings Ltd"}}},{"method":"POST","path":"/api/whatsapp/test","summary":"Send a test message to prove the configuration, rather than discovering it at the first real send.","auth":"jwt","responseExample":{"status":"sent","to":"2026-09-30"},"body":{"to":"2026-09-30","templateName":"Karoo Fresh Holdings Ltd","templateParams":{"1":"Karoo Fresh Holdings Ltd"}}}]},{"name":"External ingest (API key)","blurb":"The one surface designed for a third-party system rather than for a Ledgr client. Authenticated by the key directly, with its own scopes, and idempotent by the caller's own reference.","endpoints":[{"method":"GET","path":"/external/contacts/{contactId}/transactions?status=open&from=2026-03-01&to=2027-02-28","summary":"Billable events already posted for a contact. Scope transactions:read plus a key bound to that contact.","auth":"api-key","responseExample":[{"id":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","tenantId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","contactId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","occurredAt":"2026-09-01T09:15:00Z","description":"Consulting services — August 2026","quantity":3.0,"unitPrice":2900.0,"amount":10005.0,"currency":"ZAR","vatRate":15.0,"externalRef":"INV-0001","metadata":"text","status":"sent","invoiceId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","invoicedAt":"2026-09-01T09:15:00Z","createdAt":"2026-09-01T09:15:00Z"}]},{"method":"POST","path":"/external/contacts/{contactId}/transactions","summary":"Post a billable event. Scope transactions:write plus a bound contact, set when the key is generated under Roles → API keys.","auth":"api-key","body":{"occurredAt":"2026-08-14","description":"1 200 API calls","quantity":1200.0,"unitPrice":0.85,"currency":"ZAR","vatRate":15.0,"externalRef":"usage-2026-08-14-a1"},"responseKind":"json"},{"method":"DELETE","path":"/external/contacts/{contactId}/transactions/{id}","summary":"Remove an event before it has been invoiced.","auth":"api-key","responseKind":"none"},{"method":"POST","path":"/external/leads","summary":"Web-to-lead. Scope crm:write. Made idempotent by the caller's own external_ref under a unique index — a website form that retries on a dropped response must not create the lead twice, because two reps then phone the customer.","auth":"api-key","responseExample":{"leadId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","status":"sent"},"body":{"name":"Sipho Dlamini","companyName":"Dlamini Logistics","email":"sipho@dlamini.example","phone":"+27821234567","source":"website","estimatedValue":10005.0,"notes":"Enquiry from the website contact form.","campaign":"Spring promotion","externalRef":"INV-0001"}}]},{"name":"Inbound webhooks","blurb":"Called BY payment gateways, not by you. Each is signature-verified and, for PayFast, confirmed server-to-server before anything is marked paid — an unsigned payload carrying an attacker-chosen tenantId must never settle an invoice. The two Yoco receivers are deliberately separate: one settles a tenant's customer invoices against the tenant's own merchant account, the other settles Ledgr's own licence purchases against Ledgr's. Merging them would give one secret the power to mark any tenant's invoice paid.","endpoints":[{"method":"GET","path":"/api/channels","summary":"The company's connected online stores (market-platform T-P3.1): each store, the webhook address to paste into its notification settings, how many products matched it by SKU, how many orders became invoices, and every order it holds because Ledgr cannot fill it yet (an unknown SKU, no stock, another currency) with the reason. Credentials are never returned.","auth":"jwt","responseExample":[{"id":"5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","kind":"shopify","label":"Shopify","storeAddress":"umlazi-tees.myshopify.com","webhookUrl":"https://app.ledgr.example/webhooks/shopify/5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","productsMatched":12,"ordersTaken":48,"lastReconciledAt":"2026-10-11T02:00:04Z","stockLocationId":null,"stockLocationName":null,"payoutsNotTied":0,"waitingOrders":[{"number":"#1003","reason":"Order #1003 sells SKU MUG-02 (Enamel mug), which is no product in Ledgr. Give a product that SKU, or add it, and the order is taken.","receivedAt":"2026-10-16T09:41:12Z"}],"ledgrSetsPrices":false,"historyFrom":"2026-10-01","historyDone":false,"historyOrdersRead":250}],"module":"inventory","plan":"Business","scope":"inventory:read"},{"method":"POST","path":"/api/channels","summary":"Connect a store. Shopify is reached at its myshopify.com address only, with the custom app's Admin API access token and webhook signing secret; WooCommerce at the https address of the tenant's own site (it must resolve to a public address), with its consumer key (accessToken), consumer secret (accessSecret) and webhook secret. Takealot by the seller's account name and Marketplace API key alone (webhookSecret empty): it sends no webhooks and is read every few minutes by the channel-poll job; connecting it makes a 'Takealot warehouse' stock location for the stock Takealot holds. Every credential is held as a SecretBox envelope. The store is asked for its stock location before anything is saved, products are matched by SKU, and Ledgr's available stock (on hand less reserved) is sent at once. historyFrom (YYYY-MM-DD, default the first of this month; refused when after today or before the books are open — the opening balances or a closed month) is the day the store's past PAID orders are brought in from: the channel-poll job reads them a page per run up to the moment of connecting, through the same intake as a webhook (an order already taken is not taken twice; an unknown SKU is held), and the store's card reports historyFrom, historyDone and historyOrdersRead. Takealot's first poll starts at that day.","auth":"jwt","body":{"kind":"shopify","storeAddress":"umlazi-tees.myshopify.com","accessToken":"shpat_0123456789abcdef","webhookSecret":"whsec_0123456789abcdef","accessSecret":null,"ledgrSetsPrices":false,"historyFrom":"2026-10-01"},"responseExample":{"id":"5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","kind":"shopify","label":"Shopify","storeAddress":"umlazi-tees.myshopify.com","webhookUrl":"https://app.ledgr.example/webhooks/shopify/5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","productsMatched":12,"ordersTaken":48,"lastReconciledAt":"2026-10-11T02:00:04Z","stockLocationId":null,"stockLocationName":null,"payoutsNotTied":0,"waitingOrders":[],"ledgrSetsPrices":false,"historyFrom":"2026-10-01","historyDone":false,"historyOrdersRead":0},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"POST","path":"/api/channels/{id}/take-waiting","summary":"Take this store's held orders now, where they can be filled — a product given the order's SKU, or the stock received. Each is booked once, exactly as if it had just arrived; what still cannot be filled stays held with its reason. The channel-poll job does the same every few minutes. Needs invoices:create.","auth":"jwt","responseExample":{"taken":1,"stillWaiting":0},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"PATCH","path":"/api/channels/{id}","summary":"Change a connected store's settings. ledgrSetsPrices (off unless turned on, here or when connecting) lets Ledgr set the store's prices: each matched product's selling price, VAT included where the business charges it, is sent now and again whenever it changes in Ledgr, and the channel-poll job sends any change it missed. Shopify's variant price, WooCommerce's regular_price, Takealot's selling_price in whole rand. A store's own price is never read back into Ledgr. A field left out keeps its value. Needs the owner or an administrator.","auth":"jwt","body":{"ledgrSetsPrices":true},"responseExample":{"id":"5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","kind":"shopify","label":"Shopify","storeAddress":"umlazi-tees.myshopify.com","webhookUrl":"https://app.ledgr.example/webhooks/shopify/5d2b7c1e-9f43-4a8e-b6d0-3c1a2e4f5b67","productsMatched":12,"ordersTaken":48,"lastReconciledAt":"2026-10-11T02:00:04Z","stockLocationId":null,"stockLocationName":null,"payoutsNotTied":0,"waitingOrders":[],"ledgrSetsPrices":true},"module":"inventory","plan":"Business","scope":"inventory:write"},{"method":"DELETE","path":"/api/channels/{id}","summary":"Disconnect a store. Its credentials are discarded; the invoices its orders raised stay.","auth":"jwt","responseKind":"none","module":"inventory","plan":"Business","scope":"inventory:write"}]},{"name":"Operations & discovery","blurb":"Health, the machine-readable spec, and the background jobs as HTTP so the service can sit at min-instances 0. /health deliberately ignores the database; /readyz does not.","endpoints":[{"method":"GET","path":"/developers/playground/spec.json","summary":"This catalogue, as JSON, with each endpoint's module, plan and scope resolved. What the playground renders.","auth":"none","responseKind":"json"}]},{"name":"Point of sale","blurb":"Where a point-of-sale system posts its journals: a sale, a day's sales, a card payout, a day's stock. Reached with an API key exchanged at /auth/token and the company in X-Company-Id. Money is integer cents; every journal is posted once by the system's own clientId, and a sales journal's supplies are declared on the VAT201.","endpoints":[{"method":"POST","path":"/api/pos/journals","summary":"Post a point-of-sale journal once. A replay of the same clientId answers the journal it made (200); the first post answers 201. Refused unless it balances, every account is in the chart, and a bank leg names a bank account (bank:<id>). A sales journal's 2130 must also agree with the supplies it states at the VAT rate on its date, to a cent per till slip it summarises (supplies.receipts). A line may not name a control account a register owns (1310 Inventory, 1315, 1320, 1360, 1365, 1366, 2110, 2155-2157) or the pooled bank control 1350: the refusal names the account and the door that moves it. The goods a sales journal sold go in items [{productId, quantity, locationId?}]: they leave the stock batches at their cost (FIFO or average as the product is costed; a kit sells its parts; more than is on hand is refused before a unit moves), and the journal gains DR 5040 / CR 1310 for that cost, answered as costOfSalesCents. A replay of the same clientId relieves the stock once. Items on a journal that is not a sale, an untracked product, and a return of goods (use a credit note) are refused.","auth":"jwt","body":{"clientId":"6f1d2c7a-3b4e-3c5d-9e8f-0a1b2c3d4e5f","kind":"sales","journalDate":"2026-10-01","reference":"ruva:day:loc-main:2026-10-01:r1","memo":"Daily sales — Main","locationRef":"loc-main","locationName":"Main","currency":"ZAR","lines":[{"account":"1362","debitCents":34500,"creditCents":0,"description":"Cash takings"},{"account":"1355","debitCents":80000,"creditCents":0,"description":"Card takings"},{"account":"4010","debitCents":0,"creditCents":99565,"description":"Sales"},{"account":"2130","debitCents":0,"creditCents":14935,"description":"Output VAT"}],"supplies":{"standardRatedNetCents":99565,"zeroRatedCents":0},"items":[{"productId":"9b2e5c1a-7d34-4f08-a6c1-3e5d8f0b2a47","quantity":2,"locationId":null}]},"responseExample":{"clientId":"6f1d2c7a-3b4e-3c5d-9e8f-0a1b2c3d4e5f","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"sales","journalDate":"2026-10-01","reference":"ruva:day:loc-main:2026-10-01:r1","standardRatedNetCents":99565,"zeroRatedCents":0,"outputVatCents":14935,"inputVatCents":0,"costOfSalesCents":0},"module":"reports","plan":"Business","scope":"reports:write"},{"method":"GET","path":"/api/pos/journals/{clientId}","summary":"A point-of-sale journal by the system's own id, with the VAT it carries.","auth":"jwt","responseExample":{"clientId":"6f1d2c7a-3b4e-3c5d-9e8f-0a1b2c3d4e5f","journalId":"3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","kind":"sales","journalDate":"2026-10-01","reference":"ruva:day:loc-main:2026-10-01:r1","standardRatedNetCents":99565,"zeroRatedCents":0,"outputVatCents":14935,"inputVatCents":0,"costOfSalesCents":0},"module":"reports","plan":"Business","scope":"reports:read"},{"method":"GET","path":"/api/pos/accounts","summary":"What a point-of-sale line may name: the company's active ledger accounts by code, and its open bank accounts as bank:<id>. The pooled bank control (1350) and the controls a register owns (1310, 1315, 1320, 1360, 1365, 1366, 2110, 2155-2157) are not listed: a journal naming one is refused.","auth":"jwt","responseExample":[{"ref":"bank:3f1a7c92-5b64-4d0e-9a11-2c7e8b4f6a03","code":"bank","name":"Current"},{"ref":"1355","code":"1355","name":"Card Settlement Clearing"}],"module":"reports","plan":"Business","scope":"reports:read"}]}],"endpointCount":1573}