Workspace and billing
Check the workspace, its balance, what's been used, and what it costs.
These need a workspace key (ocp_…). Amounts are US dollars as exact decimal strings, with the same amount in millionths of a dollar in the matching _micros field.
Workspace
GET /api/v1/workspace returns { "data": { "id", "name", "slug" } }: the workspace the key belongs to.
Balance
GET /api/v1/balance
{
"data": {
"currency": "USD",
"balance": "18.420000",
"balance_micros": 18420000,
"low_balance_threshold": "5.000000",
"low_balance_threshold_micros": 5000000,
"out_of_credit_since": null,
"pauses_at": null,
"paused_at": null
}
}When the balance reaches $0, out_of_credit_since and pauses_at are set: apps pause at pauses_at unless funds are added. paused_at is set once they have. See How billing works.
Usage
GET /api/v1/usage adds up what was used between two days (UTC, both included).
Prop
Type
{
"data": [
{ "meter": "email.sent", "unit": "email", "quantity": 812, "cost": "0.284200", "cost_micros": 284200 }
],
"total_cost": "0.284200",
"total_cost_micros": 284200,
"currency": "USD",
"start": "2026-10-01",
"end": "2026-10-21"
}Each row is named by what you grouped by ("meter", "app", "end_user" or "day"), most expensive first. unpriced: true marks a meter with no price (one that isn't offered yet). The meters are listed in How billing works.
end_user is the id you passed when starting sandboxes or sending email, so you can see usage per customer.
GET /api/v1/apps/{id}/usage takes the same query for one app, and works with a key scoped to that app.
An exact window
With since (and optionally until), usage is added up over an exact window instead of whole days, from the recorded usage itself:
Prop
Type
The answer has since, until and latest_recorded_at: the newest usage recorded for the workspace, so you can tell how far the numbers reach. How soon usage is recorded depends on the meter:
| Meter | Recorded |
|---|---|
| Emails sent | when each is sent |
| Sandbox running time | at least every 10 minutes while running, and when it stops |
| Requests, CPU time, database reads, writes and storage, file operations and storage | about every hour, from the provider's analytics, stamped with when they were collected |
End users
If you run a platform, your customers are your end users: tag their work with end_user (your id for them) when you send email or start sandboxes, and you can see and cap what each one spends. At their monthly limit, new work tagged with them is refused with 402 end_user_limit_reached; your apps keep serving everyone. These need a workspace key.
| Endpoint | What it does |
|---|---|
GET /api/v1/end-users | Everyone with usage this month (UTC) or a limit of their own: what they spent and the limit that applies, biggest spenders first. Also default_monthly_limit. |
PUT /api/v1/end-users/default-spend-limit | { "monthly_limit": "5.00" }: what each end user may spend in a month unless they have their own limit. null removes it. |
PUT /api/v1/end-users/{end_user}/spend-limit | Their own limit. null means no limit for them, even with a default. URL-encode the id. |
DELETE /api/v1/end-users/{end_user}/spend-limit | Back to the default. |
{
"object": "list",
"data": [
{ "object": "end_user", "end_user": "customer_42", "spent_this_month": "4.120000", "spent_this_month_micros": 4120000, "monthly_limit": "5.000000", "limit_source": "default", "limit_reached": false }
],
"has_more": false,
"month": "2026-10",
"default_monthly_limit": "5.000000"
}Spending is checked when new work starts, so work already running finishes. To cap a whole app instead, give it a monthly limit.
Prices
GET /api/v1/prices lists today's price for every meter, for this workspace:
{
"data": [
{ "meter": "email.sent", "provider": "Email", "description": "…", "unit": "email", "price_per_million_units": "350.000000", "price_micros_per_million_units": 350000000 }
],
"currency": "USD",
"effective": "2026-10-21"
}Prices are per million units, so tiny prices stay exact. They're the providers' own prices, nothing added, and follow the providers the same day they change. null means a meter isn't offered yet. A workspace with a negotiated price sees its own.
opencloudport