> ## 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.

# Billing API

> Check wallet balance, top up credits, view transactions, and access invoices

# Billing API

Orbit is **pay-as-you-go**. There are no plan tiers or recurring subscriptions.
Each organization has a single prepaid USD wallet; top it up via one-time
Stripe Checkout sessions, and per-send / per-call / per-token charges are
deducted in real time from the wallet against an append-only
`credit_transactions` ledger.

For the full endpoint reference (status, balance, top-up, auto-top-up,
transactions, usage analytics, invoices, refunds) see
[Billing API](/api-reference/billing). This page is the multi-language
code-sample companion for the most common operations.

**Base path:** `/api/v1/billing`

***

## Get Wallet Balance

`GET /api/v1/billing/balance` (alias: `GET /api/v1/billing/credits`)

Returns the current wallet balance in USD cents plus the outbound-pause
flag.

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/balance" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/balance', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/balance", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/balance", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/balance')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/balance');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "balance_usd": 150.00,
      "balance_cents": 15000,
      "credits": 15000,
      "outbound_paused": false,
      "outbound_block_reason": null
    },
    "meta": {
      "request_id": "req_balance_001",
      "timestamp": "2026-05-16T12:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Create Top-Up Session

`POST /api/v1/billing/balance/top-up` (alias: `POST /api/v1/billing/credits/purchase`)

Creates a Stripe Checkout session (mode: `payment` — one-time charge) for
adding USD credits to the wallet. The `Idempotency-Key` header is
**required** (8-255 chars); re-submitting the same key returns the original
Checkout URL.

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X POST "https://api.orbit.devotel.io/api/v1/billing/balance/top-up" \
      -H "X-API-Key: dv_live_sk_your_key_here" \
      -H "Content-Type: application/json" \
      -d '{
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    }'
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/balance/top-up', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    }),
    })
    console.log(await res.json())
    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    headers["Content-Type"] = "application/json"
    r = requests.post("https://api.orbit.devotel.io/api/v1/billing/balance/top-up", headers=headers, json={
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    })
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("POST", "https://api.orbit.devotel.io/api/v1/billing/balance/top-up", bytes.NewBuffer([]byte(`{
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    }`)))
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))
    	req.Header.Set("Content-Type", "application/json")
    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/balance/top-up')
    req = Net::HTTP::Post.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']
    req['Content-Type'] = 'application/json'
    req.body = {
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    }.to_json
    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/balance/top-up');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),
      'Content-Type: application/json',
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, <<<JSON
    {
      "amount": 10000,
      "currency": "usd",
      "successUrl": "https://orbit.devotel.io/billing?topup=ok",
      "cancelUrl": "https://orbit.devotel.io/billing?topup=cancelled"
    }
    JSON);
    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_live_abc123..."
    },
    "meta": {
      "request_id": "req_topup_001",
      "timestamp": "2026-05-16T12:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Configure Auto-Top-Up

`PUT /api/v1/billing/auto-topup`

Keep the wallet funded automatically: when the balance falls below a threshold
you set, Orbit charges the org's saved off-session payment method to lift it
back above the trigger — no manual recharge needed. Read the current config with
`GET /api/v1/billing/auto-topup` and disable it with
`DELETE /api/v1/billing/auto-topup`.

<Note>
  The `enabled`, `threshold_minor`, and `recharge_amount_minor` parameters —
  plus a full request example — are documented in the
  [Billing API reference](/api-reference/billing#configure-auto-top-up).
</Note>

***

## List Transactions

`GET /api/v1/billing/transactions?limit=30`

Cursor-paginated read of `public.credit_transactions`. Negative
`amount_minor` values are spends; positive values are top-ups and refunds.

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "transactions": [
        {
          "id": "ct_2vXq7p9yzAbCdEf",
          "type": "credit_purchase",
          "amount_minor": 10000,
          "reference": "stripe_session:cs_live_abc123",
          "metadata": { "currency": "usd", "fx_rate": 1.0 },
          "created_at": "2026-05-16T11:22:33.444Z",
          "expires_at": null,
          "refunded_at": null
        },
        {
          "id": "ct_2vXq7p9yzAbCdEe",
          "type": "debit",
          "amount_minor": -42,
          "reference": "charge:sms_msg_01J9KP3R5W8YEQ4DXG6N7H2VKZ",
          "metadata": { "channel": "sms", "country": "1" },
          "created_at": "2026-05-16T11:21:18.901Z",
          "expires_at": null,
          "refunded_at": null
        }
      ],
      "next_cursor": {
        "cursor_ts": "2026-05-16T11:21:18.901Z",
        "cursor_id": "ct_2vXq7p9yzAbCdEe"
      },
      "has_more": true
    },
    "meta": {
      "request_id": "req_tx_001",
      "timestamp": "2026-05-16T12:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Get Per-Channel Usage

`GET /api/v1/billing/usage-by-channel?days=30`

Per-channel spend + volume breakdown sourced from `credit_transactions`.
Powers the dashboard usage card.

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/usage-by-channel?days=30');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "key": "sms",
        "channel": "sms",
        "total_messages": 3420,
        "delivered": 3380,
        "failed": 12,
        "total_cost_minor": 27360,
        "total_cost": 273.6000
      },
      {
        "key": "voice",
        "channel": "voice",
        "total_messages": 84,
        "delivered": 78,
        "failed": 6,
        "total_cost_minor": 11280,
        "total_cost": 112.8000
      }
    ],
    "meta": {
      "request_id": "req_usage_001",
      "timestamp": "2026-05-16T12:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Get Budget Cap

`GET /api/v1/billing/budget-cap`

Returns the organization's monthly budget cap (when configured), the current
calendar-month period boundaries in UTC, and month-to-date spend — so you can
warn a user before an action pushes spend past the cap. All monetary fields
are in minor units (cents).

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/budget-cap" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/budget-cap', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())
    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/budget-cap", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/budget-cap", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/budget-cap')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']

    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/budget-cap');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),
    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "cap_cents": 500000,
      "period_start": "2026-07-01T00:00:00.000Z",
      "period_end": "2026-08-01T00:00:00.000Z",
      "current_spend_cents": 128450
    },
    "meta": {
      "request_id": "req_budget_cap_001",
      "timestamp": "2026-07-03T12:00:00Z"
    }
  }
  ```
</ResponseExample>

<Note>
  `cap_cents` is `null` when no monthly cap is configured. `period_end` is
  exclusive (the first instant of next month).
</Note>

***

## Detect Spend Anomalies

`GET /api/v1/billing/spend-anomaly`

Flags channels whose current spend velocity has surged past the organization's
trailing baseline — catching a compromised account before the hard daily caps
are exhausted. All monetary fields are in minor units (cents).

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/spend-anomaly" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/spend-anomaly', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())
    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/spend-anomaly", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/spend-anomaly", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/spend-anomaly')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']

    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/spend-anomaly');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),
    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "anomalies": [
        {
          "channel": "sms",
          "baseline_daily_minor": 4200,
          "today_spend_minor": 96000,
          "projected_daily_minor": 288000,
          "surge_ratio": 68.6,
          "severity": "critical"
        }
      ],
      "detected": true,
      "baseline_days": 14,
      "surge_multiplier": 10,
      "min_projected_daily_minor": 25000,
      "day_fraction_elapsed": 0.333
    },
    "meta": {
      "request_id": "req_spend_anomaly_001",
      "timestamp": "2026-07-03T08:00:00Z"
    }
  }
  ```
</ResponseExample>

<Note>
  `surge_ratio` is `projected_daily_minor ÷ baseline_daily_minor`, or `null`
  for a channel with no prior spend (a cold-start surge). `severity` is `high`
  or `critical`. See the full
  [Billing API reference](/api-reference/billing#budget-cap-and-spend-monitoring)
  for every field.
</Note>

***

## List Invoices

`GET /api/v1/billing/invoices`

Retrieve the org's invoices, newest first. Results are cursor-paginated.

<ParamField query="status" type="string">
  Filter by lifecycle status. One of `draft`, `issued`, `paid`, `void`, `synced`.
</ParamField>

<ParamField query="cursor" type="string">
  Opaque pagination cursor. Pass the `next_cursor` value from the previous page
  to fetch the next one.
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Maximum number of invoices to return. Minimum `1`, maximum `100`.
</ParamField>

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/billing/invoices?limit=25" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/billing/invoices', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/billing/invoices", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/billing/invoices", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/billing/invoices')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/billing/invoices');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "invoices": [
        {
          "id": "kix7Gsf7nYNitX4",
          "invoice_number": "INV-2026-003",
          "status": "paid",
          "currency": "USD",
          "amount_due": "0.00",
          "total": "100.00",
          "subtotal": "100.00",
          "invoice_date": "2026-05-16T11:22:33Z",
          "due_date": "2026-05-31T23:59:59Z",
          "period_start": "2026-05-01T00:00:00Z",
          "period_end": "2026-05-31T23:59:59Z",
          "hosted_invoice_url": "https://my.withorb.com/view/kix7Gsf7nYNitX4",
          "invoice_pdf": "https://my.withorb.com/invoices/kix7Gsf7nYNitX4.pdf",
          "issued_at": "2026-05-16T11:22:33Z",
          "paid_at": "2026-05-16T12:00:00Z"
        }
      ],
      "has_more": true,
      "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0xNiJ9"
    },
    "meta": {
      "request_id": "req_inv_001",
      "timestamp": "2026-05-16T12:00:00Z"
    }
  }
  ```
</ResponseExample>

<Note>
  Monetary fields (`amount_due`, `total`, `subtotal`) are decimal strings in the
  major currency unit (e.g. `"100.00"` is \$100.00) — no division required.
  `next_cursor` is `null` and `has_more` is `false` on the final page.
</Note>

***

## Refunds (owner only)

`POST /api/v1/billing/refunds`

Issue a Stripe refund against a specific top-up `credit_transaction` lot,
within 30 days of the original purchase. `GET /api/v1/billing/refunds` lists
the org's refund history. Both endpoints are restricted to the org owner role —
unexpected refunds against a prepaid wallet are high-impact and hard to reverse.

<Note>
  See [Refunds](/api-reference/billing#refunds-owner-only) in the full Billing
  API reference for the complete description.
</Note>
