API Changelog
Dated record of additions, deprecations, and breaking changes to the Emofy Developer API, derived from the OpenAPI snapshot diff.
Scope. This page is the Developer API changelog — additive endpoints, field additions, deprecations, and (operator-approved) breaking changes to the public
/api/v1/*surface. It is generated from the committed OpenAPI snapshot diff byscripts/generate-api-changelog.mjs. It is not the in-product content-CMS changelog (modules/content/changelog), which is a separate, org-authored feature surface.
Unreleased
Added
GET /api/v1/usage— organization API usage time-series (requests, errors, p95 latency, rate-limit hits) in daily UTC buckets.GET /api/v1/usage/keys/{apiKeyId}— the same time-series scoped to a single API key the organization owns.
Changed
-
All
/api/v1/*responses may now carry anX-Quota-Warning: trueheader when the organization is over its configured monthly request quota. In the default rollout mode this is informational only and does not block the request. -
Every
/api/v1/*operation now publishes a concrete2xxresponse schema in the OpenAPI document (previously the response body was unmodelled). This is additive to the contract — the@emofy/dev-sdkaccessors are now response-typed and the Scalar reference renders each shape. -
Internal columns removed from response bodies (security-positive). Several reads previously serialized bare database rows, leaking internal fields onto the wire — tenant id (
orgId), soft-delete marker (deletedAt), audit-actor ids (createdById,markedById,gradedById,invitedBy,grantedBy,addedBy,createdBy,updatedBy), Convex-bridge columns (clientKey,convexId,source,archiveSeq), the direct-DMparticipantHash, the trusted-contact PIN state (pinHash,pinSetAt, …), and sensitive profile PII (phone,address). These are now dropped from the public response contract (academic, family, messaging, profiles, tasks, feed and identity reads). Domain fields keep their existing wire shape unchanged; the one intentional secret,POST /api/v1/apps/{id}/install→credential.appSecret, is preserved.
Deprecated
-
Legacy messaging endpoints retired with
410 Gone—GET /api/v1/conversations,GET /api/v1/conversations/{id}andGET /api/v1/channelsnow return410 Gonefor every caller, including keys with a validmessages:read/channels:readgrant. These routes exposed org-wide conversation metadata without a participant check and are retired for security reasons; the sunset window never serves200. Every410response carriesDeprecation: true,Sunset(HTTP-date, retirement + 30 days) andLink; rel="sunset"headers, plus a migration pointer inerror.message(error.code: GONE).Migration mapping (the V1 replacement is not a drop-in — path, scope and response shape all differ):
Dimension Legacy V1 replacement Route GET /api/v1/conversations,GET /api/v1/conversations/{id},GET /api/v1/channelsGET /api/v1/messaging/conversationsScope messages:read/channels:readconversations:readShape raw paginated {items, total, page, limit}user-scoped {groups, visibleDirects}Physical removal of the routes follows in a separate release once route analytics show 30 consecutive zero-hit days on the retired endpoints.