BillingReceiptExternalPayload billing.receipt.external@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.receipt.external.v1.json

billing.receipt.external v1 (OpenVibe.Billing server/ops/external.js record). An EXTERNAL receipt (ADR-012): a tip paid on a creator's own provider account (PowerChat route direct). The money never touches OpenVibe (no journal entry); Billing announces it once per payment, only when BILLING_AUTHORITY=billing and the receiving account is mapped to a creator. OpenVibe.Tips celebrates it (chat line, overlay alert, goal). Envelope: subject { type: provider_receipt, id: <provider>:<payment id> }, visibility internal, priority important, actor service:billing.

Fields

FieldTypeRequiredDescriptionConstraints
classificationconstyes
  • = "EXTERNAL"
providerstringyes
  • pattern ^[a-z][a-z0-9_-]{1,39}$
receipt_refstringyes<provider>:<payment id>, e.g. powerchat:…
provider_event_idstringyesThe provider's id of the payment, stable across redeliveries.
  • minLength 1
  • maxLength 200
delivery_idstringyesThe webhook delivery that carried it.
streameridentity.subject-refyes
receiving_accountobjectyes
  • no other fields
receiving_account.providerstringyes
receiving_account.idstring | nullyes
receiving_account.usernamestring | nullyes
amount_centsintegeryes
  • minimum 1
  • maximum 100000000
currencyconstyes
  • = "usd-cents"
value_bitsintegeryesBilling's value of the money in bits.
  • minimum 0
donor_namestring | nullyesnull when anonymous.
  • maxLength 80
anonymousbooleanyes
messagestring | nullyes
  • maxLength 500
app_refstring | nullyes
app_purposestring | nullyes
  • maxLength 120
occurred_atstring | nullyesThe provider's timestamp as it sent it.
testbooleanyes
ratesobjectyesRate snapshot.
rates.bits_per_usdnumberyes

Examples

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

Valid: anonymous
{
  "classification": "EXTERNAL",
  "provider": "powerchat",
  "receipt_ref": "powerchat:ext-1",
  "provider_event_id": "ext-1",
  "delivery_id": "dlv-ext-1",
  "streamer": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "receiving_account": {
    "provider": "powerchat",
    "id": "981",
    "username": "japaneseoldguy"
  },
  "amount_cents": 1234,
  "currency": "usd-cents",
  "value_bits": 1234,
  "donor_name": null,
  "anonymous": true,
  "message": null,
  "app_ref": null,
  "app_purpose": null,
  "occurred_at": "2026-09-23T20:00:00Z",
  "test": false,
  "rates": {
    "bits_per_usd": 100
  }
}
Valid: powerchat-tip
{
  "classification": "EXTERNAL",
  "provider": "powerchat",
  "receipt_ref": "powerchat:ext-1",
  "provider_event_id": "ext-1",
  "delivery_id": "dlv-ext-1",
  "streamer": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "receiving_account": {
    "provider": "powerchat",
    "id": "981",
    "username": "japaneseoldguy"
  },
  "amount_cents": 1234,
  "currency": "usd-cents",
  "value_bits": 1234,
  "donor_name": "Generous Fan",
  "anonymous": false,
  "message": "love the stream",
  "app_ref": null,
  "app_purpose": "goal:12",
  "occurred_at": "2026-09-23T20:00:00Z",
  "test": false,
  "rates": {
    "bits_per_usd": 100
  }
}
Rejected: booked-classification
{
  "classification": "SITE",
  "provider": "powerchat",
  "receipt_ref": "powerchat:ext-1",
  "provider_event_id": "ext-1",
  "delivery_id": "dlv-ext-1",
  "streamer": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "receiving_account": {
    "provider": "powerchat",
    "id": "981",
    "username": "japaneseoldguy"
  },
  "amount_cents": 1234,
  "currency": "usd-cents",
  "value_bits": 1234,
  "donor_name": "Generous Fan",
  "anonymous": false,
  "message": "love the stream",
  "app_ref": null,
  "app_purpose": "goal:12",
  "occurred_at": "2026-09-23T20:00:00Z",
  "test": false,
  "rates": {
    "bits_per_usd": 100
  }
}
Rejected: zero-amount
{
  "classification": "EXTERNAL",
  "provider": "powerchat",
  "receipt_ref": "powerchat:ext-1",
  "provider_event_id": "ext-1",
  "delivery_id": "dlv-ext-1",
  "streamer": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "receiving_account": {
    "provider": "powerchat",
    "id": "981",
    "username": "japaneseoldguy"
  },
  "amount_cents": 0,
  "currency": "usd-cents",
  "value_bits": 1234,
  "donor_name": "Generous Fan",
  "anonymous": false,
  "message": "love the stream",
  "app_ref": null,
  "app_purpose": "goal:12",
  "occurred_at": "2026-09-23T20:00:00Z",
  "test": false,
  "rates": {
    "bits_per_usd": 100
  }
}

Validate

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