Skip to content

Event catalog ​

This catalog lists GoodVision event types, triggers, and fields. Events use versioned names and are delivered through approved, active Webhook subscriptions.

For signature verification, token validation, deduplication, and acknowledgements, see Receive webhooks. Fields, enums, and permissions follow the event schema provided by the current Application's API product.

Complete subscription envelope ​

This complete business event represents activation and contains every required field. Plaintext HTTP delivery adds a top-level verification_token: validate and remove it to obtain this envelope. Encrypted delivery requires signature verification, decryption, and Token validation first.

json
{
  "event_id": "evt_demo_activated",
  "event_type": "oem.subscription.activated.v1",
  "schema_version": "1",
  "occurred_at": "2026-10-06T00:00:00Z",
  "producer": "opaque",
  "tenant_id": "org_customer_demo",
  "resource_id": "sub_demo_cancel",
  "resource_version": 2,
  "correlation_id": "req_demo_activation",
  "data": {
    "id": "sub_demo_cancel",
    "organization_id": "org_customer_demo",
    "open_platform_application_id": "app_demo_saas",
    "environment": "sandbox",
    "product_tenant_id": "tenant_demo_cancel",
    "party_id": "party_customer_demo",
    "order_id": "order_demo_initial",
    "product_code": "relaydesk",
    "plan_code": "basic_monthly_demo",
    "plan_version": 1,
    "status": "active",
    "current_period_start": "2026-10-06T00:00:00Z",
    "current_period_end": "2026-11-06T00:00:00Z",
    "status_effective_at": "2026-10-06T00:00:00Z",
    "payment_reference": "payment_demo_initial",
    "operation_id": "op_demo_activation",
    "reason_code": "example_activation",
    "resource_version": 2,
    "created_at": "2026-10-05T23:55:00Z",
    "updated_at": "2026-10-06T00:00:00Z"
  }
}

All IDs, plans, and reason codes are synthetic. producer: "opaque" is a display placeholder for an opaque source; use the issued schema for actual source enums. Do not hard-code the placeholder or example reason codes. Download JSON or see the complete HTTP request with headers, Token, and reproducible signature.

Every top-level field below is required for subscription events:

FieldTypeMeaning and validation
event_idstringStable business event ID; Inbox unique key
event_typestringComplete versioned name from the table; matches the header
schema_versionstringCurrently "1", not integer 1
occurred_atRFC3339 stringBusiness event time, not the signing timestamp
producerstringOpaque source; validate against the issued schema
tenant_idstringPurchasing customer Organization; equals data.organization_id, not the application's owner Organization
resource_idstringSaaS subscription ID; equals data.id
resource_versioninteger ≥ 1Subscription version; equals data.resource_version
correlation_idstringDiagnostic correlation, never a deduplication key
dataobjectCurrent subscription summary; fields below

Validate fields against the current event schema. Open objects may ignore additive fields within a supported major version. Objects with additionalProperties: false must reject or isolate unknown fields. Reject or isolate unsupported major versions rather than parsing them as an older format.

Required subscription data fields ​

All 19 subscription events share this summary. Do not send or handle only {id, status}. Field combinations must match the event and current state.

FieldTypeMeaning
idstringSubscription ID; matches top-level resource_id
organization_idstringPurchasing customer Organization; matches tenant_id
party_idstringCommercial customer record ID, not a user or Membership ID
product_codestringApproved product code
plan_codestringCurrent plan; remains current during a scheduled change
plan_versioninteger ≥ 1Immutable plan-definition version, not a subscription version
statusstringCurrent commercial state; must match the event table
current_period_startRFC3339 stringCurrent period start
current_period_endRFC3339 stringCurrent period end; later than start
status_effective_atRFC3339 stringWhen the current status took effect
operation_idstringAssociated commercial asynchronous operation ID, not payment proof
reason_codestringChange reason; values and meaning follow the issued contract
resource_versioninteger ≥ 1Monotonically increasing version of this subscription
created_atRFC3339 stringSubscription creation time
updated_atRFC3339 stringLatest summary update

Integration scope and state-specific fields ​

These fields are optional in the common summary. Follow the actual event and schema, and preserve missing fields rather than converting them to null.

Third-party delivery must bind an application and environment. Reject missing bindings instead of substituting a customer organization or application slug.

FieldTypePurpose
open_platform_application_id / environmentstring / sandbox or productionValidate the third-party Application/environment together; reject other scopes
application_slug / brand_profile_codestringDisplay identifiers; never replace Application ID for authorization
product_tenant_idstringCustomer tenant in the product; never replaces Organization
order_idstringOriginal commercial order; query payment outcomes separately
billing_modefree / paidCommercial billing mode; free activation creates no payment evidence
upgrade_from_subscription_idstringOriginal free subscription for a paid upgrade; reconcile each subscription version independently
price_version_refstringImmutable price reference; consumers cannot override amounts
trial_ending_at / trial_endRFC3339 stringTrial reminder and trial end
renewal_window_start / grace_deadlineRFC3339 stringRenewal window opening and grace deadline
pause_end / resume_statusRFC3339 string / state stringPause end and resume state; follow actual values
cancel_at / cancel_at_period_endRFC3339 string / booleanCancellation effect time and period-end flag
pending_plan_code / pending_plan_version / pending_plan_effective_atstring / integer ≥ 1 / RFC3339 stringScheduled plan and effect time, not currently effective entitlements
ended_atRFC3339 stringEnd time matching cancellation, expiry, or termination

Subscription summaries do not provide amounts, currency, old_plan, new_plan, Role or Entitlement. Query payment details and member access through their separately authorized APIs.

Complete subscription event table ​

Event names and data.status are not always one-to-one: payment failure can enter several states, and a payment-method update does not change state. This is the complete v1 set of 20 subscription events. Related fields explain the scenario; they do not replace schema required-field definitions.

Complete event nameTriggerAllowed data.statusHandling
oem.subscription.created.v1Commercial subscription createdtrialing / pending_payment / activeRead actual state; creation does not prove payment
oem.subscription.updated.v1Subscription record revised, for example when a cancellation or restoration request is acceptedactive / trialing / trial_ending / renewal_pending / plan_change_pending / pause_pending / paused / cancellation_pending / past_due / grace_period / suspendedPreserve the revision sequence and actual current state; await confirmation rather than treating the request as completed
oem.subscription.trial_started.v1Trial beginstrialingRead period and trial_end; do not extend locally
oem.subscription.trial_ending.v1Trial-ending reminder stage beginstrial_endingRead trial_ending_at and trial_end; prompt conversion
oem.subscription.activated.v1Commercial subscription activatedactiveUpdate the subscription record; check member access separately; complete request
oem.subscription.renewal_upcoming.v1Renewal window opensrenewal_pendingRead renewal_window_start; reminder is not renewal success
oem.subscription.renewed.v1Renewal completesactiveApply new period boundaries; never add a month/year locally
oem.subscription.payment_failed.v1Subscription payment failspayment_failed / past_due / grace_periodRead actual state and grace deadline; await recovery or expiry
oem.subscription.past_due.v1Subscription enters overdue/grace handlingpast_due / grace_periodRead grace_deadline; never infer a fixed grace duration
oem.subscription.payment_method_updated.v1Payment method updatedCurrent subscription state unchangedUpdate related messaging; not payment or renewal success
oem.subscription.pause_scheduled.v1Pause scheduledpause_pendingDistinguish scheduling from effect; never infer pause time locally
oem.subscription.paused.v1Pause effectivepausedUse pause_end / resume_status and query current access
oem.subscription.resumed.v1Resume operation effectiveactive / trialing / trial_ending / renewal_pending / plan_change_pending / cancellation_pending / pausedRead actual resumed state; never force active
oem.subscription.cancellation_scheduled.v1Cancellation scheduledcancellation_pendingRead cancel_at / cancel_at_period_end; complete scenario
oem.subscription.cancelled.v1Cancellation effectivecancelledRecord ended_at, restrict and reconcile access; do not infer refund
oem.subscription.plan_change_scheduled.v1Plan change scheduledplan_change_pendingRead pending_plan_*; do not enable new entitlements early
oem.subscription.plan_changed.v1Plan change effectiveactive / trialing / trial_endingCurrent plan_code / plan_version updated; complete scenario
oem.subscription.suspended.v1Commercial subscription restrictedsuspendedRestrict access; use approved recovery
oem.subscription.expired.v1Period/grace ends and subscription expiresexpiredRead ended_at, guide resubscription; complete scenario
oem.subscription.terminated.v1Commercial subscription terminatedterminatedStop access immediately; retain history and audit

Event families ​

FamilyRepresentative events
Identity and accessidentity.registration.completed.v1, oem.product.activated.v1, oem.access_context.changed.v1
SubscriptionSee the complete names and state mappings for all 20 events, including record revisions, payment-method updates, pause, cancellation, plan changes, and expiry
Plan changesoem.subscription.plan_changed.v1
Payment resultspayment.order.created.v1, payment.intent.created.v1, payment.requires_action.v1, payment.pending.v1, payment.succeeded.v1, payment.failed.v1, payment.cancelled.v1, payment.unknown.v1
Refund resultspayment.refund.pending.v1, payment.refund.unknown.v1, payment.refund.succeeded.v1, payment.refund.failed.v1
Billing statebilling.statement.published.v1
Supportoem.support.request_received.v1, reply_created, status_changed

Only events listed in the current API access grant are delivered. Do not assume similar names or unpublished events are available.

Consumer requirements ​

  1. Deduplicate with event_id.
  2. Apply state using monotonic resource_version values.
  3. Retain correlation_id for cross-system diagnostics.
  4. Reconcile version gaps through an authorized status API.
  5. Keep secrets, tokens, and unnecessary business data out of logs.

Effective access changes ​

oem.access_context.changed.v1 means that a subject's effective access context for an Organization and Product is stale. It is not a Role, Entitlement, or Capability snapshot.

json
{
  "event_id": "evt_opaque",
  "event_type": "oem.access_context.changed.v1",
  "schema_version": "1",
  "producer": "opaque",
  "occurred_at": "2026-09-17T03:00:00Z",
  "tenant_id": "org_opaque",
  "resource_id": "membership_opaque",
  "resource_version": 42,
  "correlation_id": "req_opaque",
  "data": {
    "subject_type": "membership",
    "subject_id": "membership_opaque",
    "organization_id": "org_opaque",
    "open_platform_application_id": "app_opaque",
    "environment": "sandbox",
    "product_code": "relaydesk",
    "access_revision": 42
  }
}

After receiving an access-change event:

  1. Validate producer against the current schema. Sample placeholders cannot determine actual behavior.
  2. Check that tenant_id/organization_id identifies the purchasing customer. Match open_platform_application_id and environment exactly against server configuration; organizations or slugs cannot replace them.
  3. Confirm resource_version equals data.access_revision, verify the signature and deduplicate by event_id.
  4. Use the current application service identity with openplatform.api.invoke to call POST /open-platform/v1/applications/{id}/events/{event_id}/access-snapshot with {}. The original event selects exactly one customer and Membership. Read current roles, entitlements, capabilities and access_revision; current-user context cannot replace the target member. See Product access snapshot for requests and failure handling.
  5. Check the API-defined Entitlement for paid tiers rather than a Role named VIP. Keep access restricted if the version is uncertain or the query fails.

Member snapshots require a boolean product_access_allowed:

ResultAction
true with valid identity, Membership and ProductAccessApply current roles, entitlements and capabilities
falseClear local effective permissions and restrict access
Missing or non-booleanTreat as an invalid response and keep access restricted

Organization purchase, role names and active Membership do not establish member assignment. Upgrade receivers and clear old permission records before adopting this version, so older receivers cannot ignore the field and continue granting access.

Product access activated ​

oem.product.activated.v1 only says that ProductAccess for an Organization entered trial or active. It never enables a member by itself.

json
{
  "event_id": "evt_product_access_opaque",
  "event_type": "oem.product.activated.v1",
  "schema_version": "1",
  "producer": "opaque",
  "occurred_at": "2026-09-17T03:00:00Z",
  "tenant_id": "org_opaque",
  "resource_id": "product_access_opaque",
  "resource_version": 3,
  "correlation_id": "req_opaque",
  "data": {
    "organization_id": "org_opaque",
    "product_access_id": "product_access_opaque",
    "product_code": "relaydesk",
    "product_tenant_id": "tenant_opaque",
    "open_platform_application_id": "app_opaque",
    "environment": "sandbox",
    "status": "active",
    "version": 3
  }
}

Check Application, environment, Organization, ProductAccess ID and version. Deduplicate by event_id and use versions to prevent stale local updates. Confirm member access separately through oem.access_context.changed.v1 and an authorized query.

Payment and refund events currently use USD. payment.succeeded.v1 confirms payment; payment.refund.succeeded.v1 confirms a refund.

For pending, requires_action, unknown or failed states, wait for a later Webhook or server query. Do not activate subscriptions or access before confirmation.

The snapshot API is not yet open to standard applications. Review Product access snapshot and contact support to confirm customer-scoped read access before integration.

User and event correlation keys ​

Subscriptions belong to customer spaces; renewal has no current-login prerequisite. Membership subjects match the user-context membership_id. Public aliases do not merge spaces or subscriptions. See Applications, users and events.

Developer documentation. Internal operations access is not required.