DTO allowlist policy
Public API responses are built from explicit DTO allowlists. Adding a field to a MongoDB model, internal controller response, MCP tool result, provider payload, or coach app endpoint does not automatically add that field to the Public API. Every new Public API endpoint must document each returned field on its endpoint page. New response fields require a deliberate DTO change, Swagger update, Mintlify update, frontend plugin metadata update when relevant, and contract tests for sensitive-field omissions. The Public API does not expose these internal fields unless an endpoint page explicitly documents a safe masked or derived version:
When a public workflow needs a sensitive-derived value, return a purpose-built
field instead. Examples:
pdfAvailable instead of pdfLink, a short-lived
downloadUrl instead of a storage key, and masked bank-account identifiers
instead of full account details.
Compatibility policy
Clients should ignore unknown response fields. Clients should not depend on
object key order.
Base URL
Authentication
Resource endpoints require:POST /public/v1/oauth/token using OAuth client
credentials. Each token has explicit scopes. A request must include every scope
required by the endpoint.
Resource response envelope
Bearer resource endpoints use the Public API envelope:
Example:
Error envelopes
Bearer resource authentication, scope, validation, rate-limit, and server errors use the Public API error envelope:
Example:
error.key,
endpoint context, and documented validation rules.
Error payloads do not include stack traces, raw provider payloads, token hashes,
secrets, authorization headers, Sentry context, or database documents.
Idempotency
Bearer write requests require anIdempotency-Key header:
POST, PUT, PATCH, and DELETE resource requests.
The key is scoped to the authenticated company and Public API client.
Only successful
2xx and 3xx write responses are stored for replay. Use a
new key for a new user action, and reuse a key only for retries of the exact same
request.
Access-device contracts
/public/v1/access/* is intentionally separate from the OAuth resource
contract. It uses device-key authentication and the FITsociety application
envelope:
Access decisions return HTTP
200 for both allow and deny outcomes. Read
data.allowed and data.reasonCode. Access validation has its own per-device
rate limit and does not require Idempotency-Key.
Rate limits
Bearer resource calls are rate limited per Public API OAuth client:
Every authenticated resource response includes rate-limit data in
meta.rateLimit and rate-limit headers:
Rate-limit response:
Pagination fields
List endpoints use 1-based pagination unless explicitly documented otherwise.
Default and maximum limits differ per endpoint. The endpoint pages document the
exact cap.
Date and time rules
Range endpoints reject invalid dates,
dateTo < dateFrom, and ranges above the
documented maximum.
Numeric input rules
Public write endpoints accept JSON numbers for numeric fields. Measurement values also accept localized numeric strings such as"82,5" or "1.250,5".
Numeric fields reject display strings with units or labels:
Object ID rules
IDs are MongoDB ObjectId strings. Invalid ID shape returns400. Valid IDs that
do not belong to the authenticated company or client relationship return 404
or 403 depending on the underlying access check.
The Public API never accepts companyId from resource request bodies. The
company is always derived from the Bearer token.
Short-lived download and booking tokens
Availability tokens are not reservations. Callers should submit the token to
POST /public/v1/bookings quickly and handle stale-capacity errors.
Invoice PDF URLs are read-only metadata for an existing PDF. The Public API does
not generate missing PDFs on read endpoints.
Progress photo URLs expose a signed or normalized media URL only. The raw
storage URL, storage key, uploader actor IDs, dimensions, and file-size metadata
remain internal.