Subscription

The Subscription entity (table core_api.subscriptions) records a SaaS subscription that a workspace-tracked company holds with an external software provider. Each row captures the commercial terms โ€” plan name, monthly recurring revenue, billing cadence, period dates, and optional trial/cancellation state โ€” and anchors the subscription to both a workspace (for tenant isolation) and a company (the subscriber). Subscriptions are written by the connector sync pipeline and the reconciliation layer; they are referenced by Invoice and InvoiceTransaction for revenue-recognition and reconciliation purposes.

NamingValue
ObjectSubscription
Resource type (JSON:API type)subscription
Collection / records rootโ€” (not a records root)
REST base/v1/subscriptions
Entity classSubscription

Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.

API operations

OperationMethod & pathStatus
ListGET /v1/subscriptions๐ŸŸก Planned
RetrieveGET /v1/subscriptions/{id}๐ŸŸก Planned
CreatePOST /v1/subscriptions๐ŸŸก Planned
UpdatePATCH /v1/subscriptions/{id}๐ŸŸก Planned
DeleteDELETE /v1/subscriptions/{id}๐ŸŸก Planned

Data model

Attributes

FieldTypeRequiredConstraintsAllowed valuesDescription
subscription_id๐Ÿ”’ system โ€” UUID (string)โœ… YesUNIQUE; default gen_random_uuid()โ€”Public-facing stable identifier for the subscription. Generated server-side on creation and never changed.
providerstringโšช Nomax 255 chars; nullableโ€”Name of the billing provider or SaaS vendor (e.g. 'Stripe', 'Salesforce', 'HubSpot'). Populated by the connector sync when available; null when unknown.
plan_namestringโœ… Yesmax 255 chars; NOT NULLโ€”Human-readable name of the subscription plan as surfaced by the provider (e.g. 'Business Pro', 'Enterprise Annual').
mrrdecimal(12,2) stored as stringโœ… YesCHECK mrr >= 0; NOT NULLโ€”Monthly Recurring Revenue for this subscription, expressed in the subscription currency. For non-monthly intervals, this is the normalized monthly equivalent.
currencyenum (CurrencyCodeEnum via native DB enum currency_code_enum)โœ… YesNOT NULL; nativeEnumName: currency_code_enumISO 4217 codes: USD, EUR, GBP, JPY, CHF, CAD, AUD, NZD โ€ฆ +13 moreISO 4217 currency code for the MRR amount and subscription pricing.
billing_intervalenum (BillingIntervalEnum via native DB enum billing_interval_enum)โœ… YesNOT NULL; nativeEnumName: billing_interval_enummonthly | quarterly | yearly | one_timeHow frequently the subscription is billed. The stored value is the enum value string (e.g. 'monthly', 'one_time').
current_period_startdate (ISO 8601 date string)โœ… YesNOT NULL; columnType dateโ€”Start date of the current billing period.
current_period_enddate (ISO 8601 date string)โœ… YesNOT NULL; CHECK current_period_end >= current_period_startโ€”End date of the current billing period. Must be on or after current_period_start.
trial_startdate (ISO 8601 date string)โšช Nonullable; required when trial_end is set (CHECK trial_end IS NULL OR trial_start IS NOT NULL)โ€”Start date of the trial period. If trial_end is present, trial_start must also be present.
trial_enddate (ISO 8601 date string)โšช Nonullable; CHECK trial_end IS NULL OR trial_end >= trial_startโ€”End date of the trial period. Must be on or after trial_start when set.
canceled_attimestamp (ISO 8601 datetime string)โšช Nonullable; columnType timestamptzโ€”Timestamp when the subscription was canceled. Null for active subscriptions.
renewal_datedate (ISO 8601 date string)โšช Nonullable; columnType dateโ€”Next scheduled renewal date for the subscription.
created_at๐Ÿ”’ system โ€” timestampโœ… Yesset on create via @Property onCreate hookโ€”Server-assigned creation timestamp. Set once at insert; never updated.
updated_at๐Ÿ”’ system โ€” timestampโšช Noset on create and updated on every write via @Property onUpdate hookโ€”Server-assigned last-modification timestamp. Updated automatically by MikroORM on every flush.
deleted_at๐Ÿ”’ system โ€” timestampโšช Nonullable; soft-delete sentinel โ€” all live queries filter deleted_at IS NULLโ€”Soft-delete timestamp. When set, the subscription is logically deleted. The Hasura RLS and DataViewsService both gate on this column.

Relationships

NameTypeRequiredDescription
workspaceto-one (ManyToOne)โœ… YesThe workspace this subscription belongs to. Primary tenant-isolation anchor; every query must filter by this relationship. References core_api.workspaces.
companyto-one (ManyToOne)โœ… YesThe company (customer or vendor) that holds this subscription. Used to surface the subscription in the companies composite list and for reconciliation joins. References core_api.companies.

System-computed

  • subscription_id โ€” generated by gen_random_uuid() on insert; also initialized client-side via randomUUID() as a JS default but the DB default is authoritative
  • created_at โ€” set by @Property onCreate: () => new Date() on first flush
  • updated_at โ€” set by @Property onCreate and refreshed by @Property onUpdate: () => new Date() on every subsequent flush
  • deleted_at โ€” soft-delete sentinel written by the delete service path; never set to null once assigned; Hasura RLS and DataViewsService inject a 'deleted_at IS NULL' predicate automatically when rootHasColumn returns true
  • Composite index (workspace, company) โ€” defined via @Index({ properties: ['workspace', 'company'] }) for the common Hasura user-permission query path
  • Additional index (workspace_pk, deleted_at) โ€” added by Migration20260415130000 to cover the Hasura soft-delete scoped tenant lookup pattern
  • All domain data (provider, plan_name, mrr, billing_interval, period dates) is written by the connector sync pipeline or reconciliation layer; there is no user-facing PATCH endpoint for this entity

Example

{
  "data": {
    "type": "subscription",
    "id": "a3b7e1f2-9c44-4e8d-8b12-3d7f5a2e1c09",
    "attributes": {
      "subscription_id": "a3b7e1f2-9c44-4e8d-8b12-3d7f5a2e1c09",
      "provider": "Stripe",
      "plan_name": "Business Pro",
      "mrr": "299.00",
      "currency": "EUR",
      "billing_interval": "monthly",
      "current_period_start": "2026-05-01",
      "current_period_end": "2026-05-31",
      "trial_start": null,
      "trial_end": null,
      "canceled_at": null,
      "renewal_date": "2026-06-01",
      "created_at": "2026-04-28T14:32:00.000Z",
      "updated_at": "2026-05-01T00:00:00.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "wks_uuid_here" }
      },
      "company": {
        "data": { "type": "company", "id": "cmp_uuid_here" }
      }
    }
  }
}
Source: apps/api/src/database/entities/Subscription.ts ยท domain: workspace ยท tier: Platform