> For the complete documentation index, see [llms.txt](https://developers.share.inc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.share.inc/api-reference/models.md).

# Models

## The ActivateSubscriptionResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ActivateSubscriptionResponseDto":{"properties":{"amount":{"type":"number"},"currency":{"type":"string"},"cycleId":{"format":"uuid","type":"string"},"endDate":{"format":"date-time","type":"string"},"message":{"description":"Human-readable reason when terminal is DEFERRED or FAILED.","type":"string"},"paymentStatus":{"enum":["PENDING","EXTERNAL","PAID","WAIVED","SETTLEMENT_FAILED"],"type":"string"},"planId":{"format":"uuid","type":"string"},"startDate":{"format":"date-time","type":"string"},"subscriberId":{"format":"uuid","type":"string"},"subscriptionId":{"format":"uuid","type":"string"},"terminal":{"description":"Activation outcome. `DEFERRED` means a prerequisite is missing (CPE credentials, plan assignment).","enum":["ACTIVATED-PAID","ACTIVATED-PENDING-PAYMENT","DEFERRED","FAILED"],"type":"string"}},"required":["terminal","subscriberId","subscriptionId"],"type":"object"}}}}
```

## The AddressDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"AddressDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"object"},"region":{"type":"object"},"street":{"type":"string"}},"required":["street","city","country"],"type":"object"}}}}
```

## The AddressRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"AddressRequestDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"string"},"region":{"type":"string"},"street":{"type":"string"}},"type":"object"}}}}
```

## The ApiResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ApiResponseDto":{"properties":{},"type":"object"}}}}
```

## The BalanceEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"BalanceEntity":{"properties":{"balance":{"description":"Account balance","type":"number"},"currency":{"description":"Currency code (e.g. KES, USD)","type":"string"},"updatedAt":{"description":"Last balance update timestamp","format":"date-time","type":"string"}},"required":["balance","currency","updatedAt"],"type":"object"}}}}
```

## The BillSummaryEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"BillSummaryEntity":{"properties":{"amount":{"type":"number"},"billId":{"description":"BillingCycle ID — use as billId on invoice/receipt routes","format":"uuid","type":"string"},"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"endDate":{"format":"date-time","type":"string"},"graceEndsAt":{"description":"DEV-727 — activation-grace deadline (`BillingCycle.activationGraceExpiresAt`). Null outside the activation-grace window.","format":"date-time","nullable":true,"type":"string"},"paidAt":{"description":"DEV-727 — `PaymentTransaction.completedAt` for the cycle's linked transaction. Null when no settled payment is attached.","format":"date-time","nullable":true,"type":"string"},"paymentStatus":{"enum":["PENDING","EXTERNAL","PAID","WAIVED","SETTLEMENT_FAILED"],"type":"string"},"paymentTransactionId":{"nullable":true,"type":"object"},"planId":{"format":"uuid","type":"string"},"startDate":{"format":"date-time","type":"string"},"status":{"enum":["SCHEDULED","EXTERNAL","ACTIVE","OVERDUE","SUSPENDED","COMPLETED","CANCELLED","ARCHIVED"],"type":"string"},"subscriberId":{"format":"uuid","type":"string"},"subscriptionId":{"format":"uuid","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["billId","subscriberId","subscriptionId","planId","amount","currency","status","paymentStatus","startDate","endDate","paymentTransactionId","paidAt","graceEndsAt","createdAt","updatedAt"],"type":"object"}}}}
```

## The BillingCycleResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"BillingCycleResponseDto":{"properties":{"amount":{"type":"number"},"endDate":{"format":"date-time","type":"string"},"graceEndsAt":{"description":"Activation-grace deadline (`BillingCycle.activationGraceExpiresAt`). Null outside the activation-grace window.","format":"date-time","nullable":true,"type":"string"},"id":{"description":"BillingCycle id","format":"uuid","type":"string"},"paidAt":{"description":"`PaymentTransaction.completedAt` for the cycle's linked transaction. Null when no settled payment is attached.","format":"date-time","nullable":true,"type":"string"},"paymentStatus":{"enum":["PENDING","EXTERNAL","PAID","WAIVED","SETTLEMENT_FAILED"],"type":"string"},"startDate":{"format":"date-time","type":"string"},"status":{"enum":["SCHEDULED","EXTERNAL","ACTIVE","OVERDUE","SUSPENDED","COMPLETED","CANCELLED","ARCHIVED"],"type":"string"}},"required":["id","startDate","endDate","amount","status","paymentStatus","paidAt","graceEndsAt"],"type":"object"}}}}
```

## The BillingSplitEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"BillingSplitEntity":{"properties":{"partnerAmount":{"type":"number"},"partnerPercent":{"description":"Partner (ISP) percentage (0-100)","type":"number"},"shareAmount":{"type":"number"},"sharePercent":{"description":"Share platform percentage (0-100)","type":"number"}},"required":["sharePercent","partnerPercent","shareAmount","partnerAmount"],"type":"object"}}}}
```

## The BillingStatusEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"BillingStatusEntity":{"properties":{"balance":{"type":"number"},"currency":{"type":"string"},"currentPlanId":{"format":"uuid","nullable":true,"type":"object"},"lastPaymentDate":{"nullable":true,"type":"object"},"nextBillingDate":{"nullable":true,"type":"object"},"status":{"type":"string"},"subscriberId":{"format":"uuid","type":"string"}},"required":["subscriberId","status","currentPlanId","balance","currency","nextBillingDate","lastPaymentDate"],"type":"object"}}}}
```

## The CancelChargeRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CancelChargeRequestDto":{"properties":{"reason":{"description":"Operator-supplied reason for the cancellation. Stored on `OneTimeCharge.cancelReason` for audit + partner-side reconciliation.","maxLength":280,"type":"string"}},"required":["reason"],"type":"object"}}}}
```

## The CancelInstallationRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CancelInstallationRequestDto":{"properties":{"cancellationReason":{"description":"Free-text reason for the cancellation. Persisted on the installation record and surfaced in audit logs and partner webhooks.","maxLength":1000,"type":"string"}},"type":"object"}}}}
```

## The ChargeResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ChargeResponseDto":{"properties":{"amount":{"type":"number"},"blocksActivation":{"type":"boolean"},"cancelReason":{"type":"object"},"cancelledAt":{"format":"date-time","type":"object"},"createdAt":{"format":"date-time","type":"string"},"createdBy":{"enum":["PARTNER_API","PLATFORM_ADMIN","SPLYNX_SYNC"],"type":"string"},"currency":{"type":"string"},"description":{"maxLength":140,"type":"string"},"expiresAt":{"format":"date-time","type":"object"},"id":{"format":"uuid","type":"string"},"paidAt":{"format":"date-time","type":"object"},"partnerSplitPercent":{"description":"Locked at creation","type":"number"},"shareSplitPercent":{"description":"Locked at creation","type":"number"},"status":{"enum":["PENDING","PAID","WAIVED","CANCELLED","REFUNDED","SETTLEMENT_FAILED","ARCHIVED"],"type":"string"},"subscriberId":{"format":"uuid","type":"string"},"subscriptionId":{"format":"uuid","type":"object"},"type":{"enum":["INSTALLATION","EQUIPMENT","RECONNECTION","OTHER"],"type":"string"},"updatedAt":{"format":"date-time","type":"string"},"waiveReason":{"type":"object"},"waivedAt":{"format":"date-time","type":"object"},"waivedBy":{"type":"object"}},"required":["id","subscriberId","type","description","amount","currency","status","blocksActivation","shareSplitPercent","partnerSplitPercent","createdBy","createdAt","updatedAt"],"type":"object"}}}}
```

## The CreateChargeRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateChargeRequestDto":{"properties":{"amount":{"description":"Charge amount, in `currency` minor units / decimals","type":"number"},"blocksActivation":{"default":false,"description":"When `true` and the linked subscription is PENDING, this charge gates D2 activation until it transitions to PAID, WAIVED, or CANCELLED. Coerced to `false` (with a warning log) when the linked subscription is already ACTIVE — there is nothing to gate. Ignored when no `subscriptionId` is provided.","type":"boolean"},"currency":{"description":"ISO-4217 currency code","type":"string"},"description":{"description":"Free-text description; surfaces in subscriber SMS + receipts","maxLength":140,"type":"string"},"expiresAt":{"description":"Optional ISO-8601 expiry. PENDING charges past this timestamp are auto-cancelled by a separate cron (post-MVP). Must be in the future.","format":"date-time","type":"string"},"subscriptionId":{"description":"Optional link to a subscription. When set, the charge belongs to that specific service period; otherwise it's a subscriber-level obligation that survives subscription churn.","format":"uuid","type":"string"},"type":{"description":"Type of charge","enum":["INSTALLATION","EQUIPMENT","RECONNECTION","OTHER"],"type":"string"}},"required":["type","description","amount","currency"],"type":"object"}}}}
```

## The CreateInstallationRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateInstallationRequestDto":{"properties":{"fee":{"description":"Installation fee amount. Defaults to the plan-level installation fee when omitted. Ignored when `free=true`.","type":"number"},"free":{"default":false,"description":"When `true`, no one-time installation charge is created. The installation moves straight to `AWAITING_INSTALLATION` and the outbound provisioning jobs fire immediately.","type":"boolean"},"kind":{"default":"INITIAL","description":"Installation kind. Defaults to `INITIAL`. Use `REPLACEMENT` for a CPE swap, or `RELOCATION` for a subscriber move — for a relocation, update the parent subscription's `demarcationPointId` first via `PATCH /v1/subscriptions/:id`.","enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"notes":{"description":"Free-text operator notes (up to 1000 characters).","maxLength":1000,"type":"string"},"subscriptionId":{"description":"Subscription the installation belongs to (provider-scoped).","format":"uuid","type":"string"}},"required":["subscriptionId"],"type":"object"}}}}
```

## The CreatePlanRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreatePlanRequestDto":{"properties":{"billingCycleDays":{"description":"Length of one billing period in days","enum":[1,7,30,90,365],"type":"number"},"dataCapMb":{"description":"Monthly data allowance in MB (null = unlimited)","nullable":true,"type":"number"},"downloadSpeedMbps":{"description":"Download speed in Mbps","type":"number"},"effectiveDate":{"description":"When the package takes effect (defaults to now)","format":"date-time","type":"string"},"externalPackageId":{"description":"Package ID in the partner's platform","type":"string"},"gracePeriodDays":{"description":"Grace period in days after overdue before suspension (0-30)","type":"number"},"installationFee":{"description":"One-time installation fee","type":"number"},"planName":{"type":"string"},"planType":{"enum":["subscriber","hotspot"],"type":"string"},"priceAmount":{"description":"Cost per billing cycle","type":"number"},"priceCurrency":{"description":"ISO 4217 currency code","type":"string"},"uploadSpeedMbps":{"description":"Upload speed in Mbps","type":"number"}},"required":["planType","planName","downloadSpeedMbps","uploadSpeedMbps","priceAmount","priceCurrency","billingCycleDays"],"type":"object"}}}}
```

## The CreateSubscriberRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateSubscriberRequestDto":{"properties":{"address":{"$ref":"#/components/schemas/AddressRequestDto"},"email":{"type":"string"},"externalUserId":{"description":"Subscriber ID in the partner's platform","type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"metadata":{"description":"Arbitrary key-value metadata for the subscriber","type":"object"},"phone":{"type":"string"},"pppoePassword":{"description":"The subscriber's existing PPPoE password. Supply together with `pppoeUsername` — a one-sided pair is ignored. Never logged.","type":"string"},"pppoeUsername":{"description":"The subscriber's existing PPPoE username, captured at import time so migration reuses it instead of issuing a new one. Stored on the CPE (`authType=PPPOE`); supply together with `pppoePassword` — a one-sided pair is ignored.","type":"string"},"radiusIpAssignment":{"allOf":[{"$ref":"#/components/schemas/RadiusIpAssignmentDto"}],"description":"RADIUS IP assignment for the CPE captured at import time (static IP, default/custom pool, or dual-mode uplink). Requires the `pppoeUsername`/`pppoePassword` pair — that is what materialises the CPE this assignment is stored on. Omit for the demarcation-point default behavior; the assignment can also be set, changed, or cleared later via `PATCH /v1/subscriptions/:id`."}},"required":["externalUserId","firstName","email","phone"],"type":"object"},"AddressRequestDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"string"},"region":{"type":"string"},"street":{"type":"string"}},"type":"object"},"RadiusIpAssignmentDto":{"properties":{"ip":{"description":"IPv4 address to pin. Required for `STATIC_IP` and `DUAL_UPLINK`; rejected for the pool modes. Must be unique per RADIUS instance — a duplicate returns 422 `STATIC_IP_CONFLICT`.","type":"string"},"mode":{"description":"IP-assignment scenario for the RADIUS reply. `STATIC_IP` pins `ip` and suppresses the PPP profile attribute; `DEFAULT_POOL` suppresses the profile attribute so the NAS default pool applies; `CUSTOM_POOL` replies `Framed-Pool = poolName`; `DUAL_UPLINK` pins `ip` while keeping the demarcation-point profile attribute.","enum":["STATIC_IP","DEFAULT_POOL","CUSTOM_POOL","DUAL_UPLINK"],"type":"string"},"poolName":{"description":"NAS pool name to reply as `Framed-Pool`. Required for `CUSTOM_POOL`; rejected for the other modes.","type":"string"}},"required":["mode"],"type":"object"}}}}
```

## The CreateSubscriberResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateSubscriberResponseDto":{"properties":{"address":{"$ref":"#/components/schemas/AddressDto"},"assignedPackageId":{"description":"Share's internal package reference","type":"object"},"billingCycleEnd":{"description":"ISO date of billing expiry (activation)","format":"date-time","type":"object"},"billingCycleStart":{"description":"ISO date of current billing period start (activation)","format":"date-time","type":"object"},"createdAt":{"description":"Timestamp of subscriber creation in Share","format":"date-time","type":"string"},"email":{"type":"object"},"externalUserId":{"description":"Subscriber ID in the partner's platform","type":"string"},"firstName":{"type":"string"},"id":{"description":"Share internal identifier","type":"string"},"lastName":{"type":"object"},"metadata":{"description":"Arbitrary key-value metadata","type":"object"},"nextPlanId":{"description":"Queued plan ID for next billing cycle (mid-cycle change or migration)","format":"uuid","type":"object"},"nextPlanName":{"description":"Human-readable label of the queued plan","type":"object"},"packageName":{"description":"Human-readable plan label","type":"object"},"paymentStatus":{"description":"Payment status derived from the latest subscription. `null` when the subscriber has no subscription (no payment obligation) — e.g. a freshly created subscriber before any subscription exists.","enum":["active","pending","suspended","overdue"],"nullable":true,"type":"string"},"phone":{"type":"object"},"planChangeEffectiveDate":{"description":"ISO date when the queued plan change takes effect (current billing cycle end date)","format":"date-time","type":"object"},"pppoeUsername":{"description":"PPPoE username generated by Share","type":"object"},"serviceHandle":{"description":"Stable 13-digit handle derived from a subscriber-scoped sequence and the owning provider country code. Read-only and deterministic — safe to expose in support tooling and partner integrations as a stand-in for the internal UUID.","pattern":"^\\d{13}$","type":"string"}},"required":["id","serviceHandle","externalUserId","firstName","address","createdAt"],"type":"object"},"AddressDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"object"},"region":{"type":"object"},"street":{"type":"string"}},"required":["street","city","country"],"type":"object"}}}}
```

## The CreateSubscriptionInstallationDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateSubscriptionInstallationDto":{"properties":{"fee":{"description":"Installation fee. Defaults to the plan-level installation fee when omitted.","type":"number"},"free":{"default":false,"description":"When true, the installation is recorded as free of charge — no one-time installation charge is created.","type":"boolean"},"kind":{"default":"INITIAL","description":"Installation kind. Defaults to `INITIAL`.","enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"required":{"description":"When true, an installation record is created and linked to the new subscription.","type":"boolean"}},"required":["required"],"type":"object"}}}}
```

## The CreateSubscriptionRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"CreateSubscriptionRequestDto":{"properties":{"demarcationPointId":{"description":"Demarcation-point UUID where the CPE will be installed. Captured on the CPE record at creation time so the installer can plan the field visit.","format":"uuid","type":"string"},"gracePeriodDaysOverride":{"description":"Optional per-subscription grace period in days (renewal cycles only). Overrides the plan grace period for this one subscription — unpaid renewal cycles stay live in RADIUS this many days past the due date. Omit to use the plan default.","maximum":30,"minimum":0,"type":"number"},"installation":{"allOf":[{"$ref":"#/components/schemas/CreateSubscriptionInstallationDto"}],"description":"Optional installation requirement. When provided with `required=true`, an installation record is created together with the subscription."},"planId":{"description":"Active Share Plan ID to assign to the subscription.","format":"uuid","type":"string"},"pppoePassword":{"description":"PPPoE password. Stored alongside `pppoeUsername` on the CPE record.","type":"string"},"pppoeUsername":{"description":"PPPoE username. When supplied together with `pppoePassword`, the credentials are stored on the CPE record. The RADIUS push is driven by the installation workflow.","type":"string"},"subscriberId":{"description":"Share subscriber UUID the subscription belongs to.","format":"uuid","type":"string"}},"required":["subscriberId","planId","demarcationPointId"],"type":"object"},"CreateSubscriptionInstallationDto":{"properties":{"fee":{"description":"Installation fee. Defaults to the plan-level installation fee when omitted.","type":"number"},"free":{"default":false,"description":"When true, the installation is recorded as free of charge — no one-time installation charge is created.","type":"boolean"},"kind":{"default":"INITIAL","description":"Installation kind. Defaults to `INITIAL`.","enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"required":{"description":"When true, an installation record is created and linked to the new subscription.","type":"boolean"}},"required":["required"],"type":"object"}}}}
```

## The DeactivateImmediateResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DeactivateImmediateResponseDto":{"properties":{"archivedBillingCycles":{"description":"Number of billing cycles cascade-archived.","type":"number"},"archivedInstallations":{"description":"Number of installations cascade-archived.","type":"number"},"archivedOneTimeCharges":{"description":"Number of one-time charges cascade-archived.","type":"number"},"radiusToreDown":{"description":"True when this archive emptied the subscriber's last non-terminal subscription and therefore drove the RADIUS teardown (FreeRADIUS `DELETE_USER` + Disconnect-Request). False when sibling subscriptions remain live.","type":"boolean"},"subscriptionId":{"format":"uuid","type":"string"}},"required":["subscriptionId","archivedBillingCycles","archivedInstallations","archivedOneTimeCharges","radiusToreDown"],"type":"object"}}}}
```

## The DeactivateSubscriberRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DeactivateSubscriberRequestDto":{"properties":{"inactiveReason":{"description":"Domain reason persisted on every affected subscription. Use `ADMIN_DEACTIVATED` for the standard partner-initiated path.","enum":["GRACE_EXPIRED","ADMIN_DEACTIVATED","PLAN_REMOVED","NO_PLAN_ASSIGNED","PLAN_DISABLED","ACTIVATION_GRACE_EXPIRED"],"type":"string"},"inactiveReasonNote":{"description":"Free-text note recorded alongside `inactiveReason` for audit / support context. Max 500 chars — longer values are rejected with 400. Persisted on every affected subscription.","maxLength":500,"type":"string"},"subscriptionIds":{"description":"Optional scope: when supplied, only the listed subscriptions are deactivated and any non-listed subscription on the subscriber is left untouched. When omitted, every non-INACTIVE subscription on the subscriber is deactivated (subscriber-wide). The subscriber is suspended only when every one of the subscriber's subscriptions becomes INACTIVE.","items":{"format":"uuid","type":"string"},"type":"array"}},"required":["inactiveReason"],"type":"object"}}}}
```

## The DeactivateSubscriberResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DeactivateSubscriberResponseDto":{"properties":{"affectedSubscriptionIds":{"description":"Subscriptions that transitioned to INACTIVE on this call. Always non-empty for a 200 response (an empty target set surfaces as 409 `ALREADY_INACTIVE`).","items":{"format":"uuid","type":"string"},"type":"array"},"subscriberSuspended":{"description":"Whether the subscriber itself was suspended. True only when every one of the subscriber's subscriptions is now INACTIVE — partial-scope calls that leave any subscription live return false.","type":"boolean"},"terminal":{"description":"Terminal path taken. Currently only `DEACTIVATED` is emitted — an already-inactive call surfaces as 409 `ALREADY_INACTIVE` rather than a terminal on this response.","enum":["DEACTIVATED"],"type":"string"}},"required":["terminal","affectedSubscriptionIds","subscriberSuspended"],"type":"object"}}}}
```

## The DeletePlanResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DeletePlanResponseDto":{"properties":{"deletedAt":{"description":"When the deletion took effect.","format":"date-time","type":"string"},"planId":{"format":"uuid","type":"string"}},"required":["planId","deletedAt"],"type":"object"}}}}
```

## The DemarcationPointResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DemarcationPointResponseDto":{"properties":{"createdAt":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"label":{"description":"Operator-supplied label for the demarcation.","type":"string"},"locationId":{"description":"ID of the linked `DemarcationPointLocation` row. `null` when no location has been recorded for this demarcation.","format":"uuid","type":"object"},"nasIp":{"description":"Unique NAS IP that identifies the demarcation point.","type":"string"},"status":{"description":"Operational status of the demarcation point.","enum":["ACTIVE","MAINTENANCE","OFFLINE"],"type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","label","nasIp","createdAt","updatedAt"],"type":"object"}}}}
```

## The DisablePlanCohortCountsDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DisablePlanCohortCountsDto":{"properties":{"paidActive":{"description":"Subscriptions on this plan with a paid + non-terminal cycle. Untouched on disable; the renewal cron transitions them to INACTIVE/PLAN_DISABLED at cycle end.","type":"number"},"pendingOrNoCycle":{"description":"PENDING subscriptions or subscriptions with no non-terminal cycle. Flipped to INACTIVE/PLAN_DISABLED immediately + RADIUS suspension enqueued.","type":"number"},"queuedAway":{"description":"Subscriptions on this plan with a queued `nextPlanId` pointing at a different plan. Untouched.","type":"number"},"queuedToThisPlan":{"description":"Subscriptions with `nextPlanId` queued onto this plan. Queue is cleared; current plan unchanged.","type":"number"},"unpaidOrSuspended":{"description":"Subscriptions on this plan in OVERDUE/SUSPENDED state. Existing grace flow handles them; the renewal cron skips when `disabledAt IS NOT NULL`.","type":"number"}},"required":["paidActive","pendingOrNoCycle","queuedToThisPlan","queuedAway","unpaidOrSuspended"],"type":"object"}}}}
```

## The DisablePlanResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DisablePlanResponseDto":{"properties":{"cohortCounts":{"$ref":"#/components/schemas/DisablePlanCohortCountsDto"},"disabledAt":{"description":"When the disable took effect.","format":"date-time","type":"string"},"planId":{"format":"uuid","type":"string"}},"required":["planId","disabledAt","cohortCounts"],"type":"object"},"DisablePlanCohortCountsDto":{"properties":{"paidActive":{"description":"Subscriptions on this plan with a paid + non-terminal cycle. Untouched on disable; the renewal cron transitions them to INACTIVE/PLAN_DISABLED at cycle end.","type":"number"},"pendingOrNoCycle":{"description":"PENDING subscriptions or subscriptions with no non-terminal cycle. Flipped to INACTIVE/PLAN_DISABLED immediately + RADIUS suspension enqueued.","type":"number"},"queuedAway":{"description":"Subscriptions on this plan with a queued `nextPlanId` pointing at a different plan. Untouched.","type":"number"},"queuedToThisPlan":{"description":"Subscriptions with `nextPlanId` queued onto this plan. Queue is cleared; current plan unchanged.","type":"number"},"unpaidOrSuspended":{"description":"Subscriptions on this plan in OVERDUE/SUSPENDED state. Existing grace flow handles them; the renewal cron skips when `disabledAt IS NOT NULL`.","type":"number"}},"required":["paidActive","pendingOrNoCycle","queuedToThisPlan","queuedAway","unpaidOrSuspended"],"type":"object"}}}}
```

## The DisablePreviewResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DisablePreviewResponseDto":{"properties":{"cohortCounts":{"$ref":"#/components/schemas/DisablePlanCohortCountsDto"}},"required":["cohortCounts"],"type":"object"},"DisablePlanCohortCountsDto":{"properties":{"paidActive":{"description":"Subscriptions on this plan with a paid + non-terminal cycle. Untouched on disable; the renewal cron transitions them to INACTIVE/PLAN_DISABLED at cycle end.","type":"number"},"pendingOrNoCycle":{"description":"PENDING subscriptions or subscriptions with no non-terminal cycle. Flipped to INACTIVE/PLAN_DISABLED immediately + RADIUS suspension enqueued.","type":"number"},"queuedAway":{"description":"Subscriptions on this plan with a queued `nextPlanId` pointing at a different plan. Untouched.","type":"number"},"queuedToThisPlan":{"description":"Subscriptions with `nextPlanId` queued onto this plan. Queue is cleared; current plan unchanged.","type":"number"},"unpaidOrSuspended":{"description":"Subscriptions on this plan in OVERDUE/SUSPENDED state. Existing grace flow handles them; the renewal cron skips when `disabledAt IS NOT NULL`.","type":"number"}},"required":["paidActive","pendingOrNoCycle","queuedToThisPlan","queuedAway","unpaidOrSuspended"],"type":"object"}}}}
```

## The DuplicatePlanRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"DuplicatePlanRequestDto":{"properties":{"name":{"description":"Optional override for the new plan’s name. When omitted, the new plan is named `\"<original planName> (copy)\"`.","type":"string"}},"type":"object"}}}}
```

## The EnablePlanResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"EnablePlanResponseDto":{"properties":{"disabledAt":{"description":"Always null on a successful re-enable — surfaced for symmetry with the disable response shape (callers can branch on a single field).","format":"date-time","nullable":true,"type":"string"},"enabledAt":{"description":"When the re-enable took effect.","format":"date-time","type":"string"},"planId":{"format":"uuid","type":"string"}},"required":["planId","disabledAt","enabledAt"],"type":"object"}}}}
```

## The InboundWebhookRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InboundWebhookRequestDto":{"properties":{"data":{"description":"Event payload from the external system","type":"object"},"event":{"description":"Adapter-specific event type (e.g., Splynx event name)","type":"string"}},"required":["event","data"],"type":"object"}}}}
```

## The InitiateDepositPaybillDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InitiateDepositPaybillDto":{"properties":{"accountReference":{"description":"Account-number value to pair with `paybillNumber` in the M-Pesa prompt. Matches the top-level `accountReference` on this response — surfaced here too so the full paybill block is self-contained.","type":"string"},"balanceAmount":{"description":"Subscriber-scoped outstanding balance returned by the payments rail at request time. Differs from `totalAmount`, which is the subscription-scoped sum that this STK push targets.","type":"number"},"balanceCurrency":{"description":"ISO-4217 currency code of `balanceAmount`.","type":"string"},"externalUserId":{"description":"Subscriber id in the partner's BSS/OSS, if mapped.","type":"string"},"id":{"description":"Share internal subscriber id (the paybill resource owner).","format":"uuid","type":"string"},"paybillNumber":{"description":"M-Pesa paybill business number the subscriber enters into the paybill prompt to pay manually (fallback when the STK push is cancelled or times out).","type":"string"}},"required":["id","externalUserId","paybillNumber","accountReference","balanceAmount","balanceCurrency"],"type":"object"}}}}
```

## The InitiateDepositRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InitiateDepositRequestDto":{"properties":{"phone":{"description":"M-Pesa phone override for this STK push only. Falls back to the subscriber's stored phone when omitted; the subscriber record is never mutated by this endpoint.","type":"string"}},"type":"object"}}}}
```

## The InitiateDepositResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InitiateDepositResponseDto":{"properties":{"accountReference":{"description":"Rail-aware \"Account Number\" the subscriber types into M-PESA's paybill prompt to settle this push manually if the STK prompt is cancelled or times out. The inbound C2B callback echoes it back so the same outstanding obligations are still credited. Display it as a fallback whenever the STK push is reported as failed.","type":"string"},"billingCycleIds":{"description":"Billing cycle ids that this STK push is intended to settle (every BillingCycle on the subscription with paymentStatus=PENDING at request time). The asynchronous C2B callback drives the authoritative cycle-by-cycle settlement.","items":{"type":"string"},"type":"array"},"currency":{"description":"Currency of `totalAmount`. Inherited from the underlying billing records (always KES for current providers).","type":"string"},"message":{"description":"Message echoed from the payment rail.","type":"string"},"oneTimeChargeIds":{"description":"One-time charge ids that this STK push is intended to settle (every OneTimeCharge on the subscription with status=PENDING at request time).","items":{"type":"string"},"type":"array"},"paybill":{"allOf":[{"$ref":"#/components/schemas/InitiateDepositPaybillDto"}],"description":"Paybill routing block for the deposit, included so callers have everything needed to render the manual-paybill fallback (M-PESA paybill number + account reference + subscriber outstanding balance) without a follow-up request."},"paymentId":{"description":"Share's internal payment reference. Use this id when reconciling the M-Pesa C2B callback against the obligations listed below.","type":"string"},"status":{"description":"Outcome of the push. `INITIATED` means the STK push was accepted by the rail; the actual collection is confirmed asynchronously via the C2B callback. Failures are returned as HTTP errors, not as a `FAILED` status here.","enum":["INITIATED"],"type":"string"},"totalAmount":{"description":"Total amount pushed to the rail. Server-derived from the sum of the PENDING BillingCycles + PENDING OneTimeCharges resolved at request time.","type":"number"}},"required":["paymentId","status","totalAmount","currency","billingCycleIds","oneTimeChargeIds","accountReference","paybill"],"type":"object"},"InitiateDepositPaybillDto":{"properties":{"accountReference":{"description":"Account-number value to pair with `paybillNumber` in the M-Pesa prompt. Matches the top-level `accountReference` on this response — surfaced here too so the full paybill block is self-contained.","type":"string"},"balanceAmount":{"description":"Subscriber-scoped outstanding balance returned by the payments rail at request time. Differs from `totalAmount`, which is the subscription-scoped sum that this STK push targets.","type":"number"},"balanceCurrency":{"description":"ISO-4217 currency code of `balanceAmount`.","type":"string"},"externalUserId":{"description":"Subscriber id in the partner's BSS/OSS, if mapped.","type":"string"},"id":{"description":"Share internal subscriber id (the paybill resource owner).","format":"uuid","type":"string"},"paybillNumber":{"description":"M-Pesa paybill business number the subscriber enters into the paybill prompt to pay manually (fallback when the STK push is cancelled or times out).","type":"string"}},"required":["id","externalUserId","paybillNumber","accountReference","balanceAmount","balanceCurrency"],"type":"object"}}}}
```

## The InstallationResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InstallationResponseDto":{"properties":{"activatedAt":{"format":"date-time","type":"object"},"cancellationReason":{"type":"object"},"cancelledAt":{"format":"date-time","type":"object"},"cpeId":{"format":"uuid","type":"object"},"createdAt":{"format":"date-time","type":"string"},"externalProjectId":{"type":"object"},"externalSystem":{"type":"object"},"externalTaskId":{"type":"object"},"firstBillingCycleId":{"format":"uuid","type":"object"},"firstCyclePaidAt":{"format":"date-time","type":"object"},"id":{"format":"uuid","type":"string"},"installedAt":{"format":"date-time","type":"object"},"isFree":{"type":"boolean"},"kind":{"enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"metadata":{"additionalProperties":true,"type":"object"},"notes":{"type":"object"},"oneTimeChargeId":{"description":"Identifier of the linked one-time installation charge. Null when the installation is free, and until the charge has been created on the paid path.","format":"uuid","type":"object"},"status":{"enum":["PENDING_PAYMENT","AWAITING_INSTALLATION","AWAITING_CYCLE_PAYMENT","ACTIVATED","CANCELLED","ABANDONED","ARCHIVED"],"type":"string"},"subscriberId":{"format":"uuid","type":"string"},"subscriptionId":{"format":"uuid","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","subscriberId","subscriptionId","kind","status","isFree","createdAt","updatedAt"],"type":"object"}}}}
```

## The InvoiceEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InvoiceEntity":{"properties":{"amount":{"type":"number"},"billId":{"format":"uuid","type":"string"},"currency":{"type":"string"},"description":{"type":"string"},"dueDate":{"description":"Due-by date. Always populated for BillingCycle invoices; nullable for OneTimeCharge invoices (DEV-827) — `OneTimeCharge.expiresAt` is optional on the schema.","format":"date-time","nullable":true,"type":"string"},"issuedAt":{"format":"date-time","type":"string"},"items":{"items":{"$ref":"#/components/schemas/InvoiceItemEntity"},"type":"array"},"split":{"allOf":[{"$ref":"#/components/schemas/BillingSplitEntity"}],"description":"Revenue split breakdown for the cycle. Null when the cycle has no split policy stamped.","nullable":true,"type":"object"},"status":{"type":"string"},"subscriberId":{"format":"uuid","type":"string"}},"required":["billId","subscriberId","amount","currency","status","issuedAt","dueDate","description","items","split"],"type":"object"},"InvoiceItemEntity":{"properties":{"description":{"type":"string"},"quantity":{"type":"number"},"total":{"type":"number"},"unitPrice":{"type":"number"}},"required":["description","quantity","unitPrice","total"],"type":"object"},"BillingSplitEntity":{"properties":{"partnerAmount":{"type":"number"},"partnerPercent":{"description":"Partner (ISP) percentage (0-100)","type":"number"},"shareAmount":{"type":"number"},"sharePercent":{"description":"Share platform percentage (0-100)","type":"number"}},"required":["sharePercent","partnerPercent","shareAmount","partnerAmount"],"type":"object"}}}}
```

## The InvoiceItemEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"InvoiceItemEntity":{"properties":{"description":{"type":"string"},"quantity":{"type":"number"},"total":{"type":"number"},"unitPrice":{"type":"number"}},"required":["description","quantity","unitPrice","total"],"type":"object"}}}}
```

## The ListSubscriberSettledPaymentsResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ListSubscriberSettledPaymentsResponseDto":{"properties":{"balance":{"description":"Subscriber's current ledger balance at request time. Positive values are credit on file; negative values are outstanding debt.","type":"number"},"currency":{"description":"Currency of `balance` (and of the item amounts).","type":"string"},"hasMore":{"description":"`true` when there is at least one more page.","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/SubscriberSettledPaymentItemDto"},"type":"array"},"limit":{"description":"Page size actually applied (after clamping).","maximum":100,"minimum":1,"type":"number"},"nextCursor":{"description":"Cursor for the next page when more pages remain; otherwise `null`. Pass it back as the `cursor` query param.","type":"object"}},"required":["items","balance","currency","limit","hasMore"],"type":"object"},"SubscriberSettledPaymentItemDto":{"properties":{"amount":{"description":"Ledger-truthful amount — summed over the credit entries of the settled deposit posting.","minimum":0,"type":"number"},"billId":{"description":"Billing cycle id the payment settled — `null` for one-time charge / ad-hoc settlements.","type":"object"},"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"dueDate":{"description":"Due date of the obligation this payment settled: the billing cycle end date when the payment closed a cycle, the one-time charge expiry when it closed a charge, `null` for ad-hoc top-ups that match neither.","format":"date-time","type":"object"},"id":{"description":"Payment identifier. Doubles as the cursor handle for the next page.","type":"string"},"ledgerTransactionId":{"description":"Linked ledger transaction id — `null` for the rare COMPLETED row without a ledger posting yet.","type":"object"},"paymentDate":{"description":"Settlement time (creation time when unknown).","format":"date-time","type":"string"},"paymentMethod":{"description":"Payment method the settlement arrived on.","enum":["CARD","BANK","MOBILE_MONEY","WALLET","CRYPTO"],"type":"string"},"planId":{"format":"uuid","type":"object"},"planName":{"type":"object"},"planType":{"type":"object"},"speed":{"description":"Display speed e.g. `\"50mbps\"`. `\"—\"` when unknown.","type":"string"},"status":{"description":"Always `COMPLETED` — this feed filters out non-settled rows on the server.","enum":["COMPLETED"],"type":"string"}},"required":["id","amount","currency","status","paymentMethod","paymentDate","createdAt","speed"],"type":"object"}}}}
```

## The MigrateSubscriptionInstallationDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"MigrateSubscriptionInstallationDto":{"properties":{"fee":{"description":"Installation fee. Defaults to the plan-level installation fee when omitted.","type":"number"},"free":{"default":false,"description":"When true, the installation is recorded free of charge — no one-time installation charge is created.","type":"boolean"},"kind":{"default":"REPLACEMENT","description":"Installation kind. Defaults to `REPLACEMENT`.","enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"required":{"description":"When true, an installation record and one-time charge are created on the scheduled successor.","type":"boolean"}},"required":["required"],"type":"object"}}}}
```

## The MigrateSubscriptionRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"MigrateSubscriptionRequestDto":{"properties":{"demarcationPointId":{"description":"Resolved Share DemarcationPoint UUID stamped on the successor subscription + CPE. Absent → the subscription is stranded (no RADIUS push until a demarcation point is assigned).","format":"uuid","type":"string"},"endBillingCycleDate":{"description":"ISO date — the external service’s cutover / end-of-billing-cycle date. Must be in the future. On the free path it anchors the zero-amount PAID lead-in `[now, endBillingCycleDate]`; on the scheduled path it is the cutover at which the payable successor activates.","type":"string"},"externalServiceId":{"description":"Per-service idempotency key (the external service id). Repeat calls with the same `(subscriberId, externalServiceId)` are idempotent — the existing rows are returned, no duplicate is created. Distinct ids let a subscriber be migrated for N concurrent services.","type":"string"},"free":{"default":false,"description":"Free-immediate migration (`true`) vs scheduled payable migration (`false`, default). Free-immediate archives the external subscription now and activates the Share plan immediately with a zero-amount PAID lead-in; `installation` MUST be omitted (rejected with 422).","type":"boolean"},"installation":{"allOf":[{"$ref":"#/components/schemas/MigrateSubscriptionInstallationDto"}],"description":"Scheduled path only — spawns an installation (`kind` defaults `REPLACEMENT`) + one-time charge on the successor. MUST be omitted when `free = true` (rejected with 422)."},"name":{"description":"Human label for the external subscription (the operator’s service name).","type":"string"},"planId":{"description":"Active target Share Plan UUID the subscriber migrates onto.","format":"uuid","type":"string"},"pppoePassword":{"description":"Existing PPPoE password. Supply together with `pppoeUsername`. Never logged.","type":"string"},"pppoeUsername":{"description":"Existing PPPoE username to reuse on the migrated CPE. Supply together with `pppoePassword` — a one-sided pair is ignored.","type":"string"},"subscriberId":{"description":"Existing Share subscriber UUID the migrated service belongs to.","format":"uuid","type":"string"}},"required":["subscriberId","planId","endBillingCycleDate"],"type":"object"},"MigrateSubscriptionInstallationDto":{"properties":{"fee":{"description":"Installation fee. Defaults to the plan-level installation fee when omitted.","type":"number"},"free":{"default":false,"description":"When true, the installation is recorded free of charge — no one-time installation charge is created.","type":"boolean"},"kind":{"default":"REPLACEMENT","description":"Installation kind. Defaults to `REPLACEMENT`.","enum":["INITIAL","REPLACEMENT","RELOCATION"],"type":"string"},"required":{"description":"When true, an installation record and one-time charge are created on the scheduled successor.","type":"boolean"}},"required":["required"],"type":"object"}}}}
```

## The MigrateSubscriptionResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"MigrateSubscriptionResponseDto":{"properties":{"alreadyExisted":{"description":"Scheduled path — `true` when an existing SCHEDULED successor was returned (idempotent replay on `(subscriberId, externalServiceId)`).","type":"boolean"},"currentSubscriptionId":{"description":"The external subscription (Sub A). Archived after the free-immediate replace; live (external) on the scheduled path until cutover.","format":"uuid","type":"string"},"free":{"description":"Whether this migration ran the free-immediate (`true`) or scheduled payable (`false`) path.","type":"boolean"},"idempotentReplay":{"description":"Free path — `true` when an existing Share-native replacement was returned (idempotent replay on `(subscriberId, externalServiceId)`).","type":"boolean"},"targetSubscriptionId":{"description":"The Share-native target subscription (Sub B) — the ACTIVE replacement (free path) or the SCHEDULED successor (scheduled path).","format":"uuid","type":"string"}},"required":["currentSubscriptionId","targetSubscriptionId","free"],"type":"object"}}}}
```

## The Object object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"Object":{"properties":{},"type":"object"}}}}
```

## The OutstandingItemResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"OutstandingItemResponseDto":{"properties":{"amount":{"type":"number"},"createdAt":{"description":"Row creation timestamp. The merged list is sorted by this field DESC (newest obligation first).","format":"date-time","type":"string"},"currency":{"type":"string"},"description":{"description":"`CHARGE` only — operator-facing description. `null` for cycles.","nullable":true,"type":"object"},"endDate":{"description":"`BILLING_CYCLE` only — cycle end date (the due date). `null` for charges.","format":"date-time","nullable":true,"type":"string"},"expiresAt":{"description":"`CHARGE` only — `OneTimeCharge.expiresAt` deadline. `null` when the charge has no deadline or for cycles.","format":"date-time","nullable":true,"type":"string"},"graceEndsAt":{"description":"`BILLING_CYCLE` only — activation-grace deadline (`BillingCycle.activationGraceExpiresAt`). `null` outside the activation-grace window or for charges.","format":"date-time","nullable":true,"type":"string"},"id":{"description":"`OneTimeCharge.id` for `CHARGE` rows, `BillingCycle.id` for `BILLING_CYCLE` rows.","format":"uuid","type":"string"},"kind":{"description":"Row discriminator. `CHARGE` rows carry `type` / `description` / `expiresAt`; `BILLING_CYCLE` rows carry `startDate` / `endDate` / `graceEndsAt`.","enum":["CHARGE","BILLING_CYCLE"],"type":"string"},"startDate":{"description":"`BILLING_CYCLE` only — cycle start date. `null` for charges.","format":"date-time","nullable":true,"type":"string"},"status":{"description":"For `CHARGE` rows this is a `OneTimeChargeStatus`; for `BILLING_CYCLE` rows a `BillingPaymentStatus`. Always `PENDING` or `SETTLEMENT_FAILED`.","enum":["PENDING","SETTLEMENT_FAILED"],"type":"string"},"type":{"description":"`CHARGE` only — one-time charge type. `null` for cycles.","enum":["INSTALLATION","EQUIPMENT","RECONNECTION","OTHER"],"nullable":true,"type":"string"}},"required":["kind","id","amount","currency","status","createdAt"],"type":"object"}}}}
```

## The PaybillResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"PaybillResponseDto":{"properties":{"accountReference":{"description":"Account reference for the payment","type":"string"},"balanceAmount":{"description":"Outstanding balance","type":"number"},"balanceCurrency":{"description":"ISO 4217 currency code","type":"string"},"externalUserId":{"description":"User ID in the partner's platform","type":"string"},"id":{"description":"Share internal user ID","format":"uuid","type":"string"},"paybillNumber":{"description":"Paybill number for mobile money payments","type":"string"}},"required":["id","externalUserId","paybillNumber","accountReference","balanceAmount","balanceCurrency"],"type":"object"}}}}
```

## The PaymentStatusResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"PaymentStatusResponseDto":{"properties":{"billingCycleEnd":{"description":"End of current billing period","format":"date-time","type":"string"},"daysRemaining":{"description":"Days remaining in current billing cycle","type":"number"},"externalUserId":{"description":"User ID in the partner's platform","type":"string"},"gracePeriodEnd":{"description":"When grace period ends (if applicable)","format":"date-time","type":"object"},"id":{"description":"Share internal user ID","format":"uuid","type":"string"},"nextPaymentDue":{"description":"Next payment due date","format":"date-time","type":"string"},"paymentStatus":{"description":"Current payment status","enum":["active","expired","suspended","grace_period"],"type":"string"}},"required":["id","externalUserId","paymentStatus","billingCycleEnd","nextPaymentDue","daysRemaining"],"type":"object"}}}}
```

## The PlanResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"PlanResponseDto":{"properties":{"billingCycleDays":{"description":"Length of one billing period in days (1, 7, 30, 90, or 365)","type":"number"},"createdAt":{"format":"date-time","type":"string"},"dataCapMb":{"description":"Monthly data allowance in MB (null = unlimited)","nullable":true,"type":"number"},"disabledAt":{"description":"Timestamp when the plan was disabled (null = active). Disabled plans are retained but cannot be assigned to new subscriptions; cohort 1 subs continue until the next renewal cycle.","format":"date-time","nullable":true,"type":"string"},"downloadSpeedMbps":{"description":"Download speed in Mbps","type":"number"},"effectiveDate":{"description":"When the package takes effect","format":"date-time","nullable":true,"type":"string"},"externalPackageId":{"description":"Package ID in the partner's platform","nullable":true,"type":"string"},"gracePeriodDays":{"description":"Grace period in days after overdue before suspension (0-30)","nullable":true,"type":"number"},"id":{"description":"Share internal identifier","format":"uuid","type":"string"},"installationFee":{"description":"One-time installation fee","type":"number"},"isActive":{"type":"boolean"},"planName":{"type":"string"},"planType":{"enum":["subscriber","hotspot"],"type":"string"},"priceAmount":{"description":"Cost per billing cycle","type":"number"},"priceCurrency":{"description":"ISO 4217 currency code","type":"string"},"radiusGroupName":{"description":"FreeRADIUS group name (generated by the backend, read-only)","nullable":true,"type":"string"},"speed":{"description":"Legacy speed field (mirrors download Mbps for backwards compatibility)","type":"number"},"updatedAt":{"format":"date-time","type":"string"},"uploadSpeedMbps":{"description":"Upload speed in Mbps","type":"number"}},"required":["id","externalPackageId","planType","planName","downloadSpeedMbps","uploadSpeedMbps","speed","priceAmount","priceCurrency","billingCycleDays","installationFee","isActive","createdAt","updatedAt"],"type":"object"}}}}
```

## The PushPaymentRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"PushPaymentRequestDto":{"properties":{"packageId":{"description":"Package ID this payment covers","format":"uuid","type":"string"},"paymentAmount":{"description":"Payment amount","type":"number"},"paymentCurrency":{"description":"ISO 4217 currency code","type":"string"},"paymentMethod":{"description":"Payment method used","enum":["mobile_money","card","bank_transfer","cash"],"type":"string"},"thirdPartyPaymentRef":{"description":"Partner's internal payment reference","type":"string"}},"required":["paymentAmount","paymentCurrency","paymentMethod"],"type":"object"}}}}
```

## The PushPaymentResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"PushPaymentResponseDto":{"properties":{"billingCycleEnd":{"description":"End of current billing period","format":"date-time","type":"object"},"billingCycleStart":{"description":"Start of current billing period","format":"date-time","type":"object"},"externalUserId":{"description":"User ID in the partner's platform","type":"string"},"gracePeriodEnd":{"description":"When grace period ends (hard cutoff)","format":"date-time","type":"object"},"id":{"description":"Share internal user ID","format":"uuid","type":"string"},"nextPaymentDue":{"description":"Next payment due date","format":"date-time","type":"string"},"packageId":{"description":"Package this payment covers","format":"uuid","type":"object"},"paymentAmount":{"type":"number"},"paymentCurrency":{"description":"ISO 4217 currency code","type":"string"},"paymentEventType":{"description":"Payment event type","enum":["payment_received","payment_failed","payment_expired","refund_issued"],"type":"string"},"paymentMethod":{"description":"Payment method used","enum":["mobile_money","card","bank_transfer","cash"],"type":"string"},"paymentStatus":{"description":"Current payment status","enum":["active","expired","suspended","grace_period"],"type":"string"},"timestamp":{"format":"date-time","type":"string"},"transactionId":{"description":"Share's payment reference","type":"string"}},"required":["transactionId","id","externalUserId","paymentEventType","paymentAmount","paymentCurrency","paymentMethod","paymentStatus","nextPaymentDue","timestamp"],"type":"object"}}}}
```

## The RadiusIpAssignmentDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"RadiusIpAssignmentDto":{"properties":{"ip":{"description":"IPv4 address to pin. Required for `STATIC_IP` and `DUAL_UPLINK`; rejected for the pool modes. Must be unique per RADIUS instance — a duplicate returns 422 `STATIC_IP_CONFLICT`.","type":"string"},"mode":{"description":"IP-assignment scenario for the RADIUS reply. `STATIC_IP` pins `ip` and suppresses the PPP profile attribute; `DEFAULT_POOL` suppresses the profile attribute so the NAS default pool applies; `CUSTOM_POOL` replies `Framed-Pool = poolName`; `DUAL_UPLINK` pins `ip` while keeping the demarcation-point profile attribute.","enum":["STATIC_IP","DEFAULT_POOL","CUSTOM_POOL","DUAL_UPLINK"],"type":"string"},"poolName":{"description":"NAS pool name to reply as `Framed-Pool`. Required for `CUSTOM_POOL`; rejected for the other modes.","type":"string"}},"required":["mode"],"type":"object"}}}}
```

## The ReceiptEntity object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ReceiptEntity":{"properties":{"amount":{"type":"number"},"billId":{"format":"uuid","type":"string"},"currency":{"type":"string"},"paidAt":{"format":"date-time","type":"string"},"paymentMethod":{"type":"string"},"receiptId":{"format":"uuid","type":"string"},"split":{"allOf":[{"$ref":"#/components/schemas/BillingSplitEntity"}],"description":"Revenue split breakdown for the cycle. Null when the cycle has no split policy stamped.","nullable":true,"type":"object"},"subscriberId":{"format":"uuid","type":"string"},"transactionReference":{"type":"string"}},"required":["receiptId","billId","subscriberId","amount","currency","paidAt","paymentMethod","transactionReference","split"],"type":"object"},"BillingSplitEntity":{"properties":{"partnerAmount":{"type":"number"},"partnerPercent":{"description":"Partner (ISP) percentage (0-100)","type":"number"},"shareAmount":{"type":"number"},"sharePercent":{"description":"Share platform percentage (0-100)","type":"number"}},"required":["sharePercent","partnerPercent","shareAmount","partnerAmount"],"type":"object"}}}}
```

## The RegisterWebhookRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"RegisterWebhookRequestDto":{"properties":{"apiVersion":{"description":"Envelope version pinned to this subscription. Date-stamped versioning; defaults to the latest stable version.","enum":["2026-05-22"],"type":"string"},"description":{"description":"Human-readable label for this webhook","type":"string"},"events":{"description":"Events to subscribe to. Legacy `user.*` names are accepted on input and rewritten to the canonical `subscriber.*` form.","items":{"enum":["payment.received","payment.failed","payment.expired","refund.issued","billing.cycle_started","billing.cycle_ending","billing.overdue","billing.suspended","subscriber.created","subscriber.updated","subscriber.suspended","subscriber.activated","subscriber.deleted","subscriber.terminated","subscriber.charge.created","subscription.created","subscription.updated","subscription.plan_change_queued","subscription.plan_change_applied","subscription.plan_change_rejected","subscription.plan_removed_queued","subscription.plan_removed","subscription.deactivated","subscription.override_applied","subscription.override_queued","subscription.override_rejected","installation.created","installation.updated","network.session_started","network.session_ended","network.throttled","plan.created","plan.updated","plan.deleted","user.created","user.updated","user.suspended","user.activated"],"type":"string"},"type":"array"},"headers":{"description":"Custom headers to send with each webhook POST. The X-Share-* delivery headers (signature, timestamp, event-id, event-type, delivery-id, delivery-attempt) are added automatically and cannot be overridden here.","items":{"$ref":"#/components/schemas/WebhookHeaderDto"},"type":"array"},"signingSecret":{"description":"Shared secret used for the X-Share-Signature HMAC-SHA256 over `<timestamp>.<raw-body>`. If omitted, Share generates one.","type":"string"},"url":{"description":"URL the events will be delivered to via HTTP POST. Must be https. Delivery is additionally refused at send time if the host resolves to a loopback, link-local, private, or cloud-metadata address.","type":"string"}},"required":["url","events"],"type":"object"},"WebhookHeaderDto":{"properties":{"name":{"description":"Header name. Custom headers ride alongside the auto-generated X-Share-* delivery headers.","type":"string"},"value":{"description":"Header value. Custom headers may not override X-Share-* delivery headers (X-Share-Signature, X-Share-Timestamp, X-Share-Event-Id, X-Share-Event-Type, X-Share-Delivery-Id, X-Share-Delivery-Attempt).","type":"string"}},"required":["name","value"],"type":"object"}}}}
```

## The ScheduleCancellationRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"ScheduleCancellationRequestDto":{"properties":{"reason":{"description":"Optional free-text rationale for the scheduled cancellation. Persisted on the subscription alongside the finalize date for audit.","maxLength":500,"type":"string"}},"type":"object"}}}}
```

## The SendPaymentInstructionsRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SendPaymentInstructionsRequestDto":{"properties":{"channel":{"default":"sms","description":"Channel to deliver the paybill prompt on. Defaults to `sms`. When omitted the endpoint always uses SMS — it does not fan out to both.","enum":["sms","email"],"type":"string"}},"type":"object"}}}}
```

## The SendPaymentInstructionsResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SendPaymentInstructionsResponseDto":{"properties":{"success":{"description":"Whether the communications router actually dispatched the prompt on the requested channel. `false` indicates the router skipped the send (missing template, missing recipient address).","type":"boolean"}},"required":["success"],"type":"object"}}}}
```

## The SendPdfResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SendPdfResponseDto":{"properties":{"delivered":{"description":"True once the email has been enqueued for delivery. Final delivery state is reported separately by the communications service.","type":"boolean"},"messageId":{"description":"Provider message identifier, when available synchronously. Absent for asynchronous deliveries.","nullable":true,"type":"string"}},"required":["delivered"],"type":"object"}}}}
```

## The SubscriberCountResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SubscriberCountResponseDto":{"properties":{"activeOnPlan":{"description":"Subscriptions where `planId == :id` and status is ACTIVE or PENDING.","type":"number"},"count":{"description":"`activeOnPlan + queuedForPlan`. Convenience aggregate.","type":"number"},"queuedForPlan":{"description":"Subscriptions queued onto this plan via `nextPlanId`. INACTIVE subs are excluded so a stale queue on a dead row does not inflate the count.","type":"number"}},"required":["count","activeOnPlan","queuedForPlan"],"type":"object"}}}}
```

## The SubscriberResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SubscriberResponseDto":{"properties":{"address":{"$ref":"#/components/schemas/AddressDto"},"assignedPackageId":{"description":"Share's internal package reference","type":"object"},"billingCycleEnd":{"description":"ISO date of billing expiry","format":"date-time","type":"object"},"billingCycleStart":{"description":"ISO date of current billing period start","format":"date-time","type":"object"},"createdAt":{"format":"date-time","type":"string"},"email":{"type":"object"},"externalUserId":{"description":"Subscriber ID in the partner's platform","type":"string"},"firstName":{"type":"string"},"id":{"description":"Share internal identifier","type":"string"},"lastName":{"type":"object"},"metadata":{"description":"Arbitrary key-value metadata","type":"object"},"nextPlanId":{"description":"Queued plan ID for next billing cycle (mid-cycle change or migration)","format":"uuid","type":"object"},"nextPlanName":{"description":"Human-readable label of the queued plan","type":"object"},"packageName":{"description":"Human-readable plan label","type":"object"},"paymentStatus":{"description":"Payment status aggregated across the subscriber’s live subscriptions (an ACTIVE subscription wins over PENDING/SCHEDULED). `null` when the subscriber has no subscription (no payment obligation).","enum":["active","pending","suspended","overdue"],"nullable":true,"type":"string"},"phone":{"type":"object"},"planChangeEffectiveDate":{"description":"ISO date when the queued plan change takes effect (current billing cycle end date)","format":"date-time","type":"object"},"pppoeUsername":{"description":"PPPoE username generated by Share","type":"object"},"providerId":{"description":"Owning provider (partner) id","format":"uuid","type":"string"},"providerName":{"description":"Owning provider display name (network name); null when the provider has none on file","nullable":true,"type":"object"},"serviceHandle":{"description":"Stable 13-digit handle derived from a subscriber-scoped sequence and the owning provider country code. Read-only and deterministic — safe to expose in support tooling and partner integrations as a stand-in for the internal UUID.","pattern":"^\\d{13}$","type":"string"},"updatedAt":{"format":"date-time","type":"object"}},"required":["id","providerId","serviceHandle","externalUserId","firstName","createdAt"],"type":"object"},"AddressDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"object"},"region":{"type":"object"},"street":{"type":"string"}},"required":["street","city","country"],"type":"object"}}}}
```

## The SubscriberSettledPaymentItemDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SubscriberSettledPaymentItemDto":{"properties":{"amount":{"description":"Ledger-truthful amount — summed over the credit entries of the settled deposit posting.","minimum":0,"type":"number"},"billId":{"description":"Billing cycle id the payment settled — `null` for one-time charge / ad-hoc settlements.","type":"object"},"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"dueDate":{"description":"Due date of the obligation this payment settled: the billing cycle end date when the payment closed a cycle, the one-time charge expiry when it closed a charge, `null` for ad-hoc top-ups that match neither.","format":"date-time","type":"object"},"id":{"description":"Payment identifier. Doubles as the cursor handle for the next page.","type":"string"},"ledgerTransactionId":{"description":"Linked ledger transaction id — `null` for the rare COMPLETED row without a ledger posting yet.","type":"object"},"paymentDate":{"description":"Settlement time (creation time when unknown).","format":"date-time","type":"string"},"paymentMethod":{"description":"Payment method the settlement arrived on.","enum":["CARD","BANK","MOBILE_MONEY","WALLET","CRYPTO"],"type":"string"},"planId":{"format":"uuid","type":"object"},"planName":{"type":"object"},"planType":{"type":"object"},"speed":{"description":"Display speed e.g. `\"50mbps\"`. `\"—\"` when unknown.","type":"string"},"status":{"description":"Always `COMPLETED` — this feed filters out non-settled rows on the server.","enum":["COMPLETED"],"type":"string"}},"required":["id","amount","currency","status","paymentMethod","paymentDate","createdAt","speed"],"type":"object"}}}}
```

## The SubscriptionPricingOverrideResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SubscriptionPricingOverrideResponseDto":{"properties":{"authorizedBy":{"description":"Identifier of the user that authorized the override.","format":"uuid","type":"object"},"createdAt":{"format":"date-time","type":"string"},"durationOverride":{"description":"Active duration override in days; overrides the plan duration.","type":"object"},"expiresAt":{"description":"Optional expiry — after this point the override is treated as cleared.","format":"date-time","type":"object"},"nextDurationOverride":{"description":"Queued duration override in days — promoted to the active value at the next renewal.","type":"object"},"nextPriceOverride":{"description":"Queued price override — promoted to the active value at the next renewal.","type":"object"},"nextSpeedOverride":{"description":"Queued speed override in Mbps — promoted to the active value at the next renewal.","type":"object"},"priceOverride":{"description":"Active price override; overrides the plan price.","type":"object"},"reason":{"description":"Operator-supplied rationale for the override.","type":"object"},"speedOverride":{"description":"Active speed override in Mbps; overrides the plan speed.","type":"object"},"updatedAt":{"format":"date-time","type":"string"}},"required":["createdAt","updatedAt"],"type":"object"}}}}
```

## The SubscriptionResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SubscriptionResponseDto":{"properties":{"createdAt":{"format":"date-time","type":"string"},"demarcationPointId":{"format":"uuid","type":"object"},"expiresAt":{"format":"date-time","type":"string"},"gracePeriodDaysOverride":{"description":"Per-subscription grace period in days (renewal cycles only), overriding the plan grace period for this subscription. `null` when not set — the subscription uses the plan grace period.","maximum":30,"minimum":0,"nullable":true,"type":"object"},"id":{"format":"uuid","type":"string"},"inactiveReason":{"enum":["GRACE_EXPIRED","ADMIN_DEACTIVATED","PLAN_REMOVED","NO_PLAN_ASSIGNED","PLAN_DISABLED","ACTIVATION_GRACE_EXPIRED"],"type":"string"},"inactiveReasonNote":{"description":"Operator-supplied free-text rationale paired with `inactiveReason`. Persisted on the subscription when set during deactivation.","type":"object"},"isExternal":{"description":"True when the subscription is managed by an external BSS.","type":"boolean"},"name":{"description":"Subscription label set from the originating external service name (Splynx internet-service description). Populated for the current/non-Share migration subscription (which has no plan); null for Share-native subscriptions.","type":"object"},"nextPlanId":{"description":"Queued plan ID (set on plan-change-queued or migration-pending).","format":"uuid","type":"object"},"nextPlanName":{"type":"object"},"override":{"allOf":[{"$ref":"#/components/schemas/SubscriptionPricingOverrideResponseDto"}],"description":"Active and queued per-subscription pricing override. Populated on the detail endpoint (`GET /v1/subscriptions/:id`); the list endpoint always returns `null` here. `null` when no override has been applied."},"planId":{"format":"uuid","type":"object"},"planName":{"description":"Human-readable plan label","type":"object"},"pppoePassword":{"description":"PPPoE password on the subscriber CPE","type":"object"},"pppoeUsername":{"description":"PPPoE username on the subscriber CPE","type":"object"},"scheduledCancellationAt":{"description":"Finalize date when the subscription is scheduled for cancellation (set by `POST /v1/subscriptions/:id/deactivate`); `null` when not scheduled. Presence means \"scheduled for cancellation\": the subscription stays `ACTIVE` and keeps internet until the billing finalize cron archives it at/after this date. Cleared by `POST /v1/subscriptions/:id/cancel-scheduled-cancellation`.","format":"date-time","type":"object"},"serviceHandle":{"description":"Stable 13-digit handle derived from a per-subscription sequence and the provider country code. Read-only and deterministic — safe to expose in support tooling and partner integrations.","pattern":"^\\d{13}$","type":"string"},"startedAt":{"format":"date-time","type":"string"},"status":{"enum":["PENDING","SCHEDULED","ACTIVE","EXPIRED","SUSPENDED","AWAITING_PAYMENT_FOR_UPGRADE","INACTIVE","ARCHIVED"],"type":"string"},"subscriberId":{"format":"uuid","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"wasMigrated":{"description":"True when this subscriber was carried over from a legacy BSS during platform migration.","type":"boolean"}},"required":["id","serviceHandle","subscriberId","status","isExternal","wasMigrated","startedAt","expiresAt","createdAt","updatedAt"],"type":"object"},"SubscriptionPricingOverrideResponseDto":{"properties":{"authorizedBy":{"description":"Identifier of the user that authorized the override.","format":"uuid","type":"object"},"createdAt":{"format":"date-time","type":"string"},"durationOverride":{"description":"Active duration override in days; overrides the plan duration.","type":"object"},"expiresAt":{"description":"Optional expiry — after this point the override is treated as cleared.","format":"date-time","type":"object"},"nextDurationOverride":{"description":"Queued duration override in days — promoted to the active value at the next renewal.","type":"object"},"nextPriceOverride":{"description":"Queued price override — promoted to the active value at the next renewal.","type":"object"},"nextSpeedOverride":{"description":"Queued speed override in Mbps — promoted to the active value at the next renewal.","type":"object"},"priceOverride":{"description":"Active price override; overrides the plan price.","type":"object"},"reason":{"description":"Operator-supplied rationale for the override.","type":"object"},"speedOverride":{"description":"Active speed override in Mbps; overrides the plan speed.","type":"object"},"updatedAt":{"format":"date-time","type":"string"}},"required":["createdAt","updatedAt"],"type":"object"}}}}
```

## The SwapPreviewRejectionDetailsDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SwapPreviewRejectionDetailsDto":{"properties":{"code":{"enum":["SUBSCRIPTION_TERMINAL","PLAN_DISABLED","CONTACT_SHARE","PLAN_PRICE_BELOW_FLOOR"],"type":"string"},"details":{"description":"Code-dependent detail bag. SUBSCRIPTION_TERMINAL carries `status`; CONTACT_SHARE carries `downloadSpeedMbps` + `maxSpeedMbps`; PLAN_PRICE_BELOW_FLOOR carries `downloadSpeedMbps`, `minPriceKes`, `providedPriceKes`; PLAN_DISABLED is detail-less.","type":"object"}},"required":["code"],"type":"object"}}}}
```

## The SwapPreviewResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"SwapPreviewResponseDto":{"properties":{"predictedCoaPush":{"description":"Present only when `predictedResult=applied`. `true` when the target plan’s effective speed differs from the subscription’s current effective speed AND the subscription is currently ACTIVE — a CoA push would be enqueued.","type":"boolean"},"predictedQueuedEffectiveDate":{"description":"Present only when `predictedResult=queued`. End of the current active billing cycle — the point at which the renewal tick would promote `nextPlanId` → `planId`.","format":"date-time","type":"string"},"predictedResult":{"description":"Predicted swap-rule outcome.","enum":["applied","queued","recorded","no-op","rejected"],"type":"string"},"rejectionDetails":{"allOf":[{"$ref":"#/components/schemas/SwapPreviewRejectionDetailsDto"}],"description":"Present only when `predictedResult=rejected`. Mirrors the error shape the real update endpoint would throw."}},"required":["predictedResult"],"type":"object"},"SwapPreviewRejectionDetailsDto":{"properties":{"code":{"enum":["SUBSCRIPTION_TERMINAL","PLAN_DISABLED","CONTACT_SHARE","PLAN_PRICE_BELOW_FLOOR"],"type":"string"},"details":{"description":"Code-dependent detail bag. SUBSCRIPTION_TERMINAL carries `status`; CONTACT_SHARE carries `downloadSpeedMbps` + `maxSpeedMbps`; PLAN_PRICE_BELOW_FLOOR carries `downloadSpeedMbps`, `minPriceKes`, `providedPriceKes`; PLAN_DISABLED is detail-less.","type":"object"}},"required":["code"],"type":"object"}}}}
```

## The UpdateInstallationRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"UpdateInstallationRequestDto":{"properties":{"notes":{"description":"Free-text operator notes (up to 1000 characters).","maxLength":1000,"type":"string"}},"type":"object"}}}}
```

## The UpdatePlanRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"UpdatePlanRequestDto":{"properties":{"billingCycleDays":{"description":"Length of one billing period in days","enum":[1,7,30,90,365],"type":"number"},"dataCapMb":{"description":"Monthly data allowance in MB (null = unlimited)","nullable":true,"type":"number"},"downloadSpeedMbps":{"description":"Download speed in Mbps","type":"number"},"effectiveDate":{"description":"When the package takes effect","format":"date-time","type":"string"},"externalPackageId":{"description":"Package ID in the partner's platform","nullable":true,"type":"string"},"gracePeriodDays":{"description":"Grace period in days after overdue before suspension (0-30)","type":"number"},"installationFee":{"description":"One-time installation fee","type":"number"},"isActive":{"description":"Activate or deactivate the plan","type":"boolean"},"planName":{"type":"string"},"planType":{"enum":["subscriber","hotspot"],"type":"string"},"priceAmount":{"description":"Cost per billing cycle","type":"number"},"priceCurrency":{"description":"ISO 4217 currency code","type":"string"},"uploadSpeedMbps":{"description":"Upload speed in Mbps","type":"number"}},"type":"object"}}}}
```

## The UpdateSubscriberRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"UpdateSubscriberRequestDto":{"properties":{"address":{"$ref":"#/components/schemas/AddressRequestDto"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"metadata":{"description":"Arbitrary key-value metadata for the subscriber","type":"object"},"phone":{"type":"string"}},"type":"object"},"AddressRequestDto":{"properties":{"city":{"type":"string"},"country":{"type":"string"},"postalCode":{"type":"string"},"region":{"type":"string"},"street":{"type":"string"}},"type":"object"}}}}
```

## The UpdateSubscriptionRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"UpdateSubscriptionRequestDto":{"properties":{"cancelQueuedSwap":{"description":"Clear a queued plan swap (`nextPlanId`) without touching the current `planId`. Mutually exclusive with `planId` — sending both returns 400.","type":"boolean"},"demarcationPointId":{"description":"Move the subscription to a different demarcation point. The change is persisted on the CPE record.","format":"uuid","type":"string"},"gracePeriodDaysOverride":{"description":"Set the per-subscription grace period (days, renewal cycles only), overriding the plan grace period for this subscription. Send `null` to clear the override and revert to the plan default. Omit to leave the current value unchanged.","maximum":30,"minimum":0,"nullable":true,"type":"object"},"planId":{"description":"Change the assigned plan. Send `null` to remove the plan — the removal is queued until cycle expiry, applied immediately when the cycle has been refunded, or applied immediately when no cycle is in flight.","format":"uuid","nullable":true,"type":"object"},"pppoePassword":{"description":"Rotate the PPPoE password. See `pppoeUsername`.","type":"string"},"pppoeUsername":{"description":"Rotate the PPPoE username. The CPE record is updated and a credential push is scheduled or queued depending on cycle state.","type":"string"},"radiusIpAssignment":{"allOf":[{"$ref":"#/components/schemas/RadiusIpAssignmentDto"}],"description":"Set or change the RADIUS IP assignment on the subscription's CPE (static IP, default/custom pool, dual-mode uplink). Send `null` to clear the assignment back to the demarcation-point default. Omit to leave the current assignment untouched. A duplicate static IP on the same RADIUS instance returns 422 `STATIC_IP_CONFLICT`.","nullable":true,"type":"object"}},"type":"object"},"RadiusIpAssignmentDto":{"properties":{"ip":{"description":"IPv4 address to pin. Required for `STATIC_IP` and `DUAL_UPLINK`; rejected for the pool modes. Must be unique per RADIUS instance — a duplicate returns 422 `STATIC_IP_CONFLICT`.","type":"string"},"mode":{"description":"IP-assignment scenario for the RADIUS reply. `STATIC_IP` pins `ip` and suppresses the PPP profile attribute; `DEFAULT_POOL` suppresses the profile attribute so the NAS default pool applies; `CUSTOM_POOL` replies `Framed-Pool = poolName`; `DUAL_UPLINK` pins `ip` while keeping the demarcation-point profile attribute.","enum":["STATIC_IP","DEFAULT_POOL","CUSTOM_POOL","DUAL_UPLINK"],"type":"string"},"poolName":{"description":"NAS pool name to reply as `Framed-Pool`. Required for `CUSTOM_POOL`; rejected for the other modes.","type":"string"}},"required":["mode"],"type":"object"}}}}
```

## The UpdateWebhookRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"UpdateWebhookRequestDto":{"properties":{"apiVersion":{"description":"Envelope version pinned to this subscription. Date-stamped versioning.","enum":["2026-05-22"],"type":"string"},"description":{"description":"Human-readable label for this webhook","type":"string"},"events":{"description":"Events to subscribe to (replaces existing list)","items":{"enum":["payment.received","payment.failed","payment.expired","refund.issued","billing.cycle_started","billing.cycle_ending","billing.overdue","billing.suspended","subscriber.created","subscriber.updated","subscriber.suspended","subscriber.activated","subscriber.deleted","subscriber.terminated","subscriber.charge.created","subscription.created","subscription.updated","subscription.plan_change_queued","subscription.plan_change_applied","subscription.plan_change_rejected","subscription.plan_removed_queued","subscription.plan_removed","subscription.deactivated","subscription.override_applied","subscription.override_queued","subscription.override_rejected","installation.created","installation.updated","network.session_started","network.session_ended","network.throttled","plan.created","plan.updated","plan.deleted","user.created","user.updated","user.suspended","user.activated"],"type":"string"},"type":"array"},"headers":{"description":"Headers to send with each webhook POST (replaces existing list)","items":{"$ref":"#/components/schemas/WebhookHeaderDto"},"type":"array"},"isActive":{"description":"Enable or disable this webhook","type":"boolean"},"signingSecret":{"description":"New shared secret for HMAC-SHA256 signature","type":"string"},"url":{"description":"URL where Share will POST event payloads. Must be https. Delivery is additionally refused at send time if the host resolves to a loopback, link-local, private, or cloud-metadata address.","type":"string"}},"type":"object"},"WebhookHeaderDto":{"properties":{"name":{"description":"Header name. Custom headers ride alongside the auto-generated X-Share-* delivery headers.","type":"string"},"value":{"description":"Header value. Custom headers may not override X-Share-* delivery headers (X-Share-Signature, X-Share-Timestamp, X-Share-Event-Id, X-Share-Event-Type, X-Share-Delivery-Id, X-Share-Delivery-Attempt).","type":"string"}},"required":["name","value"],"type":"object"}}}}
```

## The WaiveChargeRequestDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"WaiveChargeRequestDto":{"properties":{"reason":{"description":"Optional reason for the waiver. Stored on `OneTimeCharge.waiveReason` for audit and partner reconciliation.","maxLength":280,"type":"string"}},"type":"object"}}}}
```

## The WebhookHeaderDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"WebhookHeaderDto":{"properties":{"name":{"description":"Header name. Custom headers ride alongside the auto-generated X-Share-* delivery headers.","type":"string"},"value":{"description":"Header value. Custom headers may not override X-Share-* delivery headers (X-Share-Signature, X-Share-Timestamp, X-Share-Event-Id, X-Share-Event-Type, X-Share-Delivery-Id, X-Share-Delivery-Attempt).","type":"string"}},"required":["name","value"],"type":"object"}}}}
```

## The WebhookHeaderResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"WebhookHeaderResponseDto":{"properties":{"name":{"type":"string"},"value":{"description":"Value with {{signature}} placeholder masked in responses","type":"string"}},"required":["name","value"],"type":"object"}}}}
```

## The WebhookResponseDto object

```json
{"openapi":"3.0.0","info":{"title":"Share API","version":"1.0"},"components":{"schemas":{"WebhookResponseDto":{"properties":{"apiVersion":{"description":"Date-stamped envelope version pinned to this subscription.","type":"string"},"createdAt":{"format":"date-time","type":"string"},"description":{"description":"Human-readable label","type":"object"},"events":{"description":"Subscribed events","items":{"type":"array"},"type":"array"},"headers":{"description":"Headers sent with each webhook POST","items":{"$ref":"#/components/schemas/WebhookHeaderResponseDto"},"type":"array"},"id":{"description":"Webhook subscription ID","format":"uuid","type":"string"},"isActive":{"type":"boolean"},"lastTriggeredAt":{"description":"Last time this webhook was triggered","format":"date-time","type":"object"},"signingSecret":{"description":"Masked signing secret (full value only returned on creation)","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"url":{"description":"URL where Share POSTs event payloads","type":"string"}},"required":["id","url","events","headers","isActive","signingSecret","apiVersion","createdAt","updatedAt"],"type":"object"},"WebhookHeaderResponseDto":{"properties":{"name":{"type":"string"},"value":{"description":"Value with {{signature}} placeholder masked in responses","type":"string"}},"required":["name","value"],"type":"object"}}}}
```
