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