> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Worked reseller flow: create, finalize, and read back

> Copy-pasteable request and response samples for the subaccount lifecycle chain a reseller actually runs — create, verify domain, finalize, then usage, pricing, and rating — plus the non-empty response shapes for the GET routes.

## The lifecycle at a glance

A subaccount is a child organization under your parent org. It starts
`pending` the moment you create it, and it only becomes billing-active when
you finalize. Create it, optionally attach branding and a custom domain,
fund it, verify ownership of the domain, then flip it to active — and read
back usage, pricing, and status. Every role gate on this page is **owner or
admin on the parent organization**, except `suspend`/`reactivate` (owner
only). Worked responses below use empty-path-safe ids, not shell echoes.

```
POST /subaccounts ─► POST /{id}/domains ─► POST /{id}/domains/{domainId}/verify
        │                    (optional)
        ▼
POST /{id}/transfer-credits ─► POST /{id}/finalize ─► status: active ─►
  GET /{id}/usage • GET /{id}/pricing • GET /{id}/rate-deck
```

## Worked sequence: create → fund → finalize

### 1. Create the subaccount

`POST /api/v1/subaccounts` takes a minimal body — a `name` is enough; plan,
limits, and reseller pricing can follow as separate calls. The response
carries the new org id and the one-time plaintext default API key.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" \
    -d '{ "name": "Rahal Industries" }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "data": {
      "id": "org_sub_rahal_00x9",
      "name": "Rahal Industries",
      "slug": "rahal-industries",
      "plan": "starter",
      "subscription_status": "pending",
      "api_key": "dv_live_sk_9PmzRu2KqLsXfY7wBcNaV4tE",
      "created_at": "2026-08-25T10:00:00Z"
    },
    "meta": { "request_id": "req_create_001", "timestamp": "2026-08-25T10:00:00Z" }
  }
  ```
</ResponseExample>

Store `api_key` before you discard the response — it is shown **once**.
Until finalization the subaccount is `pending`: reads work, but billing
metering does not start.

### 2. Fund the wallet

Push initial credits from the parent wallet; pass a `client_reference_id`
so a retried top-up replays instead of double-charging.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/transfer-credits" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" \
    -d '{ "amount_cents": 100000, "note": "Initial seed", "client_reference_id": "seed-rahal-001" }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "transferred": true,
      "amount_cents": 100000,
      "parent_balance_cents": 91500,
      "child_balance_cents": 100000
    },
    "meta": { "request_id": "req_transfer_001", "timestamp": "2026-08-25T10:00:30Z" }
  }
  ```
</ResponseExample>

### 3. Attach a custom domain (optional)

White-label hosts claim a domain and re-check its CNAME before finalizing.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/domains" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" \
    -d '{ "domain": "hub.rahal.example" }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "dom_rahal_hub_01ax",
      "organization_id": "org_sub_rahal_00x9",
      "domain": "hub.rahal.example",
      "status": "pending",
      "cname_target": "domains.orbit.devotel.io",
      "cname_verified_at": null,
      "ssl_cert_provisioned_at": null
    },
    "meta": { "request_id": "req_domain_001", "timestamp": "2026-08-25T10:01:00Z" }
  }
  ```
</ResponseExample>

Point the domain's DNS at `cname_target`, then re-check. `status` flips to
`verified` when the CNAME resolves; the SSL certificate provisions
asynchronously after that.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/domains/dom_rahal_hub_01ax/verify" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "dom_rahal_hub_01ax",
      "status": "verified",
      "cname_verified_at": "2026-08-25T10:03:00Z"
    },
    "meta": { "request_id": "req_dverify_001", "timestamp": "2026-08-25T10:03:00Z" }
  }
  ```
</ResponseExample>

### 4. Finalize

Flip the subaccount to `active`. Owner or admin on the parent. The call is
idempotent — a rerun on an already-active row is a `200` no-op, so a
retried "Launch" click is safe.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/finalize" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": { "id": "org_sub_rahal_00x9", "subscription_status": "active" },
    "meta": { "request_id": "req_finalize_001", "timestamp": "2026-08-25T10:04:00Z" }
  }
  ```
</ResponseExample>

Shortcut: `POST /api/v1/subaccounts/provision` runs create → pricing →
branding → funding → finalize as one atomic call. Reach for it when
onboarding is driven by your own portal instead of a human wizard.

## Read back: usage, pricing, and status

Once active, the reads your reseller portal makes most:

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/usage" \
    -H "X-API-Key: dv_live_sk_your_parent_key"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "subaccount_id": "org_sub_rahal_00x9",
      "credits_used": 118492,
      "messages_sent": 1214,
      "messages_received": 97,
      "calls_made": 36,
      "api_calls": 8120,
      "current_plan": "growth",
      "rate_limit_per_second": 20,
      "data_retention_days": 365
    },
    "meta": { "request_id": "req_usage_001", "timestamp": "2026-08-25T10:05:00Z" }
  }
  ```
</ResponseExample>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/pricing" \
    -H "X-API-Key: dv_live_sk_your_parent_key"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "subaccount_id": "org_sub_rahal_00x9",
      "reseller_margin_pct": 25,
      "monthly_spend_cap_cents": 5000000,
      "current_period_spend_cents": 118492
    },
    "meta": { "request_id": "req_pricing_get_001", "timestamp": "2026-08-25T10:05:30Z" }
  }
  ```
</ResponseExample>

`GET /{id}` returns the org row (`subscription_status`, `plan`, `parent`
hierarchy) — the status check the finalize step above flips. `GET
/{id}/usage/statement?period=YYYY-MM` returns the billing-grade per-day ×
meter rows the rollup endpoint folds; `GET /{id}/usage/export.csv` streams
the same figures as a CSV attachment to invoice your end-customer.

## Rating: rate deck, rate cards, and MCCMNC overrides

Subaccount pricing is a flat `reseller_margin_pct` over wholesale, plus
optional per-channel/destination markup cells (the **rate deck**) or a
named **rate card** from the parent org's price-book library. For specific
mobile operators, layer per-MCCMNC overrides — the send-path resolver
prices an SMS segment against them before falling through to the wholesale
deck.

Read the assigned deck — an empty `rate_deck` means every usage line prices
at the flat margin:

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/rate-deck" \
    -H "X-API-Key: dv_live_sk_your_parent_key"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "subaccount_id": "org_sub_rahal_00x9",
      "assigned_rate_card_id": "rc_voice_us_25",
      "rate_deck": [
        { "channel": "sms", "destination": "US", "margin_pct": 25 },
        { "channel": "voice", "destination": "US", "margin_pct": 20 }
      ]
    },
    "meta": { "request_id": "req_ratedeck_001", "timestamp": "2026-08-25T10:06:00Z" }
  }
  ```
</ResponseExample>

List the parent org's persisted cards — each carries at least one cell
family (`lane_cells` and/or `deck_cells`); cards without cells never
persist:

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.orbit.devotel.io/api/v1/subaccounts/rate-cards" \
    -H "X-API-Key: dv_live_sk_your_parent_key"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "rate_cards": [
        {
          "id": "rc_voice_us_25",
          "name": "US voice 20% + SMS US 25%",
          "lane_cells": ["voice:US:20"],
          "deck_cells": ["sms:US:25"]
        }
      ]
    },
    "meta": { "request_id": "req_ratecards_001", "timestamp": "2026-08-25T10:06:30Z" }
  }
  ```
</ResponseExample>

Upsert a per-operator override — `POST` returns the written row; `GET
/{id}/mccmnc-overrides` lists them cursor-paginated (`meta.cursor`,
`meta.has_more`, `meta.total`):

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.orbit.devotel.io/api/v1/subaccounts/org_sub_rahal_00x9/mccmnc-overrides" \
    -H "X-API-Key: dv_live_sk_your_parent_key" \
    -H "Content-Type: application/json" \
    -d '{ "mccmnc": "52503", "rate_per_unit": 0.018, "currency": "USD" }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "data": {
      "id": "mccmncOverride_01j72k",
      "mccmnc": "52503",
      "operator_name": "SingTel Singapore",
      "country": "Singapore",
      "rate_per_unit": 0.018,
      "currency": "USD",
      "created_at": "2026-08-25T10:07:00Z"
    },
    "meta": { "request_id": "req_mccmnc_001", "timestamp": "2026-08-25T10:07:00Z" }
  }
  ```
</ResponseExample>
