BillingSubscriptionCanceledPayload billing.subscription.canceled@1

Generated at from openvibe-contracts v0.33.0 and openvibe-sdk v0.5.0.

Version
1.0.0
Owner
billing
Visibility
first-party
Status
active
Compatibility
backward
Decision
ADR-012
Schema
https://openvibe.network/contracts/events/payloads/billing.subscription.canceled.v1.json

billing.subscription.canceled v1 (OpenVibe.Billing server/ops/subscriptions.js cancel). A subscription was set to cancel at period end (for Stripe, after Stripe accepted it); the paid period still runs. Envelope: subject { type: subscription, id: sub_… }, visibility internal, priority important, actor service:billing.

Fields

FieldTypeRequiredDescriptionConstraints
subscriptionobjectyes
  • no other fields
subscription.idstringyes
  • pattern ^sub_[0-9A-HJKMNP-TV-Z]{26}$
subscription.subscriberidentity.subject-refyes
subscription.streameridentity.subject-refyes
subscription.tierintegeryes
  • minimum 1
subscription.providerstringyes
subscription.provider_refstring | nullyes
subscription.routestring | nullyes
subscription.statusenumyes
  • one of "active", "canceled", "expired"
subscription.auto_renewbooleanyes
subscription.cancel_at_period_endbooleanyes
subscription.price_centsintegeryes
  • minimum 0
subscription.current_period_endstring | nullyes
subscription.created_atstringyes
subscription.updated_atstringyes
provider_syncenumyes
  • one of "not_needed", "stripe_cancel_at_period_end"
actorobjectyesWho asked: the calling principal and the person it acted for.
  • no other fields
actor.principalstring | nullyesToken sub of the caller (svc:…, usr_…).
actor.request_idstring | nullyes
actor.on_behalf_ofidentity.subject-ref

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: stripe
{
  "subscription": {
    "id": "sub_01JAB3C4D5E6F7G8H9J0K1MNQ0",
    "subscriber": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
    },
    "streamer": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    },
    "tier": 1,
    "provider": "stripe",
    "provider_ref": "sub_1Q2w3E4r5T6y",
    "route": "site",
    "status": "active",
    "auto_renew": false,
    "cancel_at_period_end": true,
    "price_cents": 499,
    "current_period_end": "2026-10-23T10:00:00.000Z",
    "created_at": "2026-09-23T10:00:00.000Z",
    "updated_at": "2026-09-23T11:00:00.000Z"
  },
  "provider_sync": "stripe_cancel_at_period_end",
  "actor": {
    "principal": "svc:vip",
    "request_id": "req_abcdefgh",
    "on_behalf_of": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
    }
  }
}
Rejected: no-actor
{
  "subscription": {
    "id": "sub_01JAB3C4D5E6F7G8H9J0K1MNQ0",
    "subscriber": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
    },
    "streamer": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    },
    "tier": 1,
    "provider": "stripe",
    "provider_ref": "sub_1Q2w3E4r5T6y",
    "route": "site",
    "status": "active",
    "auto_renew": false,
    "cancel_at_period_end": true,
    "price_cents": 499,
    "current_period_end": "2026-10-23T10:00:00.000Z",
    "created_at": "2026-09-23T10:00:00.000Z",
    "updated_at": "2026-09-23T11:00:00.000Z"
  },
  "provider_sync": "not_needed"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('billing.subscription.canceled@1', value);   // { valid, errors: [{ path, message }] }