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
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
classification | const | yes |
| |
provider | string | yes |
| |
receipt_ref | string | yes | <provider>:<payment id>, e.g. powerchat:… | |
provider_event_id | string | yes | The provider's id of the payment, stable across redeliveries. |
|
delivery_id | string | yes | The webhook delivery that carried it. | |
streamer | identity.subject-ref | yes | ||
receiving_account | object | yes |
| |
receiving_account.provider | string | yes | ||
receiving_account.id | string | null | yes | ||
receiving_account.username | string | null | yes | ||
amount_cents | integer | yes |
| |
currency | const | yes |
| |
value_bits | integer | yes | Billing's value of the money in bits. |
|
donor_name | string | null | yes | null when anonymous. |
|
anonymous | boolean | yes | ||
message | string | null | yes |
| |
app_ref | string | null | yes | ||
app_purpose | string | null | yes |
| |
occurred_at | string | null | yes | The provider's timestamp as it sent it. | |
test | boolean | yes | ||
rates | object | yes | Rate snapshot. | |
rates.bits_per_usd | number | yes |
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 }] }