API reference · Costs

Costs and budgets

Read spend and manage the limits in front of it. Concepts are on Costs and budgets.

GET/v1/costsAggregate spend.
GET/v1/budgetsList budgets in a workspace.
POST/v1/budgetsCreate a budget.
GET/v1/budgets/{budget_id}Read one.
PATCH/v1/budgets/{budget_id}Change a limit or mode.
DELETE/v1/budgets/{budget_id}Remove a budget.
GET/v1/budgets/{budget_id}/refusalsWhat it turned away.

GET /v1/costs

Aggregate the cost ledger, grouped the way you ask.

requestbash
curl -s "https://api.esy.com/v1/costs?workspaceId=$WS&groupBy=provider" \
  -H "Authorization: Bearer $ESY_API_KEY"
200 OKjson
{
  "groupBy": "provider",
  "currency": "USD",
  "estimatedUsd": 1665.31,
  "actualUsd": 1665.11,
  "entryCount": 331784,
  "buckets": [
    { "key": "openai",        "estimatedUsd": 872.33, "actualUsd": 872.13, "entryCount": 60197 },
    { "key": "anthropic",     "estimatedUsd": 700.66, "actualUsd": 700.66, "entryCount": 85892 },
    { "key": "fal",           "estimatedUsd": 91.22,  "actualUsd": 91.22,  "entryCount": 19526 },
    { "key": "cloudflare_r2", "estimatedUsd": 0.47,   "actualUsd": 0.47,   "entryCount": 104527 }
  ]
}

Note cloudflare_r2: the most ledger entries and the least money. Storage is metered on every run and costs almost nothing — sort buckets by actualUsd, not by count.

Query parameters

FieldTypeRequiredDescription
groupBystringoptionalFor example provider, workflow, operation, or period.
workspaceId / projectIduuidoptionalScope the aggregate.
workflowIdstringoptionalOne workflow only.
providerstringoptionalOne provider only.
statusenumoptionalOnly ledger rows in one cost state.
periodGranularitystringoptionalBucket size when grouping by time.
from / todatetimeoptionalISO-8601 bounds.

GET /v1/budgets

Budgets in a workspace.

workspaceId is required here — omit it and you get a 422 naming the missing query parameter. Narrow further with projectId or workflowId.

POST /v1/budgets

Create a budget.

workspaceId and limitUsd are required. Set projectId or workflowId to narrow it — there is no scope field to send. Full field reference and a worked example are on Costs and budgets.

PATCH /v1/budgets/{budget_id}

Update a budget. Send only what changes.

requestbash
curl -X PATCH https://api.esy.com/v1/budgets/budget-7a1c… \
  -H "Authorization: Bearer $ESY_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "limitUsd": 75.0 }'

Patchable: name, limitUsd, period, perRunCapUsd, enforcementMode, overageUsd. A budget’s workspace, project, and workflow are fixed at creation.

GET /v1/budgets/{budget_id}/refusals

Runs and orders this budget refused.

Each refusal records the source (run or order), the reason, and the numbers at the moment it fired. Paginated with offset/limit.