Skip to main content

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, transactions, usage analytics, invoices, refunds) see Billing API. 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.
cURL
curl -X GET "https://api.orbit.devotel.io/api/v1/billing/balance" \
  -H "X-API-Key: dv_live_sk_your_key_here" 
Node.js
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
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
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
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
$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);
{
  "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"
  }
}

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.
cURL
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"
}'
Node.js
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
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
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
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
$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);
{
  "data": {
    "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_live_abc123..."
  },
  "meta": {
    "request_id": "req_topup_001",
    "timestamp": "2026-05-16T12:00:00Z"
  }
}

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.
cURL
curl -X GET "https://api.orbit.devotel.io/api/v1/billing/transactions?limit=30" \
  -H "X-API-Key: dv_live_sk_your_key_here" 
Node.js
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
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
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
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
$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);
{
  "data": {
    "transactions": [
      {
        "id": "ct_2vXq7p9yzAbCdEf",
        "type": "topup",
        "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": "spend",
        "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"
  }
}

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.
cURL
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" 
Node.js
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
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
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
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
$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);
{
  "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"
  }
}

List Invoices

GET /api/v1/billing/invoices Retrieve past Stripe invoices and one-time payment receipts for the org.
cURL
curl -X GET "https://api.orbit.devotel.io/api/v1/billing/invoices" \
  -H "X-API-Key: dv_live_sk_your_key_here" 
Node.js
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
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
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
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
$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);
{
  "data": [
    {
      "id": "inv_abc123",
      "number": "INV-2026-003",
      "amount": 10000,
      "currency": "usd",
      "status": "paid",
      "period_start": "2026-05-01T00:00:00Z",
      "period_end": "2026-05-31T23:59:59Z",
      "pdf_url": "https://pay.stripe.com/invoice/acct_xxx/inv_abc123/pdf",
      "created_at": "2026-05-16T11:22:33Z"
    }
  ],
  "meta": {
    "request_id": "req_inv_001",
    "timestamp": "2026-05-16T12:00:00Z"
  }
}
Invoice amounts are in the smallest currency unit (e.g., cents for USD). Divide by 100 for display.