GroundIT API

Internal handoff documentation for the teams building against this deployment: the Flutter mobile app, the Sysmedac One portal, and the fintech ports. Contract only — no credentials, no tenant data.

@groundit/api 0.0.0 env production git c2b18c8e 20 documents · 1368 operations

1 · Start here

Flutter mobile team

You consume the product app API under /api/v1.

  1. Read §2 (auth), §3 (errors), §4 (pagination & idempotency) below — they apply to every operation.
  2. Open the module documents in §6 · Product app API. Employee-facing surfaces live mostly in People, Attendance & Leave, Pay & Tax, Work and Cross-cutting.
  3. Generate a client from the bundled JSON — each document downloads as one self-contained file.

Sysmedac One portal team

You call GroundIT inbound and hand users over by SSO.

  1. Platform inbound + SSO is your document — tenant lifecycle, workspace members, the RBAC mirror, impersonation, usage.
  2. Sign every call per §5 · the HMAC recipe below. These routes sit outside /api/v1.
  3. The bridge-token handover is POST /api/sso/exchange — also outside the version prefix, because you sign and link that exact path.

Fintech partners

dhanavega / PayDay+ (EWA) and interpay (KSA money movement).

  1. PayrollPort is the employer-side EWA adapter contract (ADR 0014); GroundIT is the employer side, dhanavega is the system of record.
  2. interpay is specced ahead of sandbox access (ADR 0013) and is a placeholder contract, not a live integration.

2 · Authentication — the product app API

Every /api/v1/* operation is authenticated by an opaque session cookie. No token, refresh token, or Keycloak material is ever returned to a client: the cookie is the credential, and it is HttpOnly.

Authorization is re-resolved server-side on every request. The session carries identity only; permissions come from the tenant's RBAC state, so a client must never cache or infer an allow decision. Each operation's operationId is its permission token (<module>.<resource>.<action>, ADR 0015) — that string is the single join key between this API, the RBAC catalogue, and the traceability corpus.

Tenancy is never a parameter. tenant_id never appears in a path, query, or body on the product surface: it comes from the session and is enforced in Postgres by row-level security.

3 · Errors — RFC 9457 problem+json

Every error response is application/problem+json and carries a stable machine-readable code alongside the HTTP status. Branch on code, never on detail (human text, may change) or on the status alone. Every response — success or error — also carries X-Correlation-Id; log it, and quote it when raising an issue.

{
  "type": "about:blank",
  "title": "Forbidden",
  "status": 403,
  "code": "TOKEN_DENIED",
  "detail": "human-readable, non-contractual",
  "instance": "/api/v1/employees/…",
  "correlation_id": "…"
}

The codes below are read from the running build's catalogue, so this list cannot drift from what this deployment actually emits:

Code
TOKEN_DENIED
SCOPE_DENIED
OWNERSHIP_DENIED
MAKER_EQUALS_CHECKER
STEP_UP_REQUIRED
CONSENT_REQUIRED
PLAN_LIMIT_EXCEEDED
FEATURE_NOT_IN_PLAN
TENANT_SUSPENDED
NOT_FOUND
IDEMPOTENCY_KEY_REUSE
STATE_TRANSITION_INVALID
FACE_MISMATCH
FACE_VERIFICATION_REQUIRED
TENANT_CANCELLED
VERSION_CONFLICT
VALIDATION_FAILED
WITHHOLDING_REVIEW_REQUIRED
TENANT_PAST_DUE
PRECONDITION_REQUIRED
RATE_LIMITED

The entitlement family is ordered subscription-status → feature-flag → numeric-limit and surfaces as 423 TENANT_PAST_DUE (writes blocked, reads still fine) · 402 FEATURE_NOT_IN_PLAN · 402 PLAN_LIMIT_EXCEEDED · 403 TENANT_SUSPENDED · 410 TENANT_CANCELLED. A row hidden by row-level security answers 404 NOT_FOUND, deliberately indistinguishable from an absent row.

4 · Pagination, idempotency, concurrency

5 · Platform inbound (/platform/*) and the SSO exchange

These two channels are the Sysmedac One seam. Both sit outside the /api/v1 prefix, because the caller signs (or links to) the exact wire path.

Signing an inbound /platform/* call

Every call except GET /platform/health carries three signals; any failure is a single opaque 401 that tells you nothing about which one failed.

Authorization:            Bearer <service-token plaintext>
X-Platform-Signature:     <hex lowercase HMAC-SHA256>      (X-SaasPortal-Signature also accepted)
X-Platform-Timestamp:     <epoch MILLISECONDS>             (X-SaasPortal-Timestamp also accepted)
Idempotency-Key:          <uuid>   (required on every mutation; X-Idempotency-Key also accepted)

signature = HMAC-SHA256(
    key     = <the same service-token plaintext>,
    message = timestamp + "\n" + METHOD + "\n" + path + "\n" + sha256hex(body)
)

Bridge-token SSO

POST /api/sso/exchange takes the platform's Ed25519-signed bridge token and mints a GroundIT product session (the same cookie as §2). GroundIT is a verifier only — it holds the platform's public key and never a portal credential. aud is always enforced, iss when configured, and the channel is sealed (every exchange 401) until the public key is provisioned. Full request/response shapes are in Platform inbound + SSO.

6 · Product app API — /api/v1

One document per module grouping. Audience: Flutter mobile and Sysmedac One portal / web back-office.

DocumentOpsVersionDownload
Org & Admin Config plane (legal entities, org tree, locations, shifts, leave/holiday config, pay structures, statutory hub, templates) and governance plane (RBAC catalogue, audit lens, reports, tenant config). 142 0.1.0 JSON · YAML
People Employee directory, profile 360, personal info, contacts, dependents, bank accounts, and the PII-reveal path. 91 0.1.0 JSON · YAML
Recruit Requisitions, candidates, interviews, offers, and pre-boarding hand-off. 98 0.1.0 JSON · YAML
Attendance & Leave Punches (offline sync), attendance records, regularizations, overtime, geofence events, leave applications/balances/encashment, comp-offs. 143 0.1.0 JSON · YAML
Work Projects, task boards, tasks, assignments, work entries, and timesheets. 162 0.1.0 JSON · YAML
Pay & Tax Payroll runs and their lifecycle, payslips, ESOP grants/exercises/valuations, full & final settlement, tax declarations, proofs, and regime choice. 137 0.1.0 JSON · YAML
Payroll Simple monthly payroll: tenant settings, named pay heads, employee pay, calendar months, payslips, bank advice, payments and advances. 28 0.2.0 JSON · YAML
Expense & Benefits Travel and expense claims, advances, and the benefits catalogue/enrolment. 54 0.1.0 JSON · YAML
Perform & Learn Goals, reviews, feedback, and the learning catalogue/enrolments. 92 0.1.0 JSON · YAML
Documents, Helpdesk & Assets Document vault and policies, helpdesk tickets, and asset assignment/return. 89 0.1.0 JSON · YAML
Engage & Exit Engagement moments, surveys, exit workflow, alumni, rehire, and referrals. 86 0.1.0 JSON · YAML
Comply Statutory filings and registers for India (EPFO/ESIC/TRACES/PT) and KSA (GOSI, WPS-Mudad, Nitaqat). 35 0.1.0 JSON · YAML
Fintech Earned-wage access, salary advances, employee loans, wallet/ledger, and the PayrollPort event mirror (ADR 0014/0018). 53 0.1.0 JSON · YAML
Client Billing Tenant client register, effective-dated billing rates, invoices, payments, and receivables aging for the Finance console. 27 0.1.0 JSON · YAML
Sales Pre-delivery revenue: accounts, enquiries, proposals, contracts, and licensing (ADR 0042; module 15). 27 0.1.0 JSON · YAML
Cross-cutting (xc) Search, notifications, device tokens, files, home widgets, approval inbox, delegations, sessions, virtual IDs, privacy requests, and the audit read lens. 60 0.1.0 JSON · YAML

7 · Platform inbound + SSO

DocumentOpsVersionDownload
Platform inbound + SSO Everything Sysmedac One calls on GroundIT: tenant lifecycle, workspace members, the RBAC mirror, impersonation, usage — plus POST /api/sso/exchange. Service-bearer + HMAC signed, outside the /api/v1 prefix. 31 0.2.0 JSON · YAML

8 · Fintech ports

DocumentOpsVersionDownload
PayrollPort (dhanavega EWA) The employer-side EWA adapter contract GroundIT exposes to dhanavega / PayDay+ (ADR 0014) — five capabilities plus the inbound webhook. 5 0.1.0 JSON · YAML
interpay (KSA money movement) Placeholder contract for SAR payouts and SAMA compliance (ADR 0013) — no sandbox access yet, specced ahead of integration. 5 0.1.0 JSON · YAML

9 · Public legal content

DocumentOpsVersionDownload
Public legal content Unauthenticated mobile retrieval of the published privacy policy and the existing bundled Terms and About copy; routes are outside /api/v1. 3 0.1.0 JSON · YAML

9 · How current is this?

These documents are the spec of record from planning/api-docs/openapi/, served straight off this deployment's build — not a snapshot pasted into a wiki. The repository's working contract makes them release-blocking: every change to an endpoint, DTO, error code, header, or auth requirement updates the owning OpenAPI document in the same change, and an automated check fails the build when a route the API actually serves is absent from a served document.

The spec deliberately runs ahead of the implementation — it is the full designed surface, and endpoints keep landing sprint by sprint. If an operation you need answers 404, it is specced but not yet built; ask before designing around it.