sphoroVOICEdocs
Markdown

Projects and budgets

A project is a cost centre inside your account: which team, client or campaign a call is billed to, and — if you want — a monthly ceiling that stops it spending more than that.

What a project is not

A project is not a tenant and isolates nothing. Two projects in one account can share agents, numbers and knowledge bases, and a key scoped to your account can read across all of them. If you need one customer's data unreachable from another's, that is separate accounts, not separate projects.

Nor is it an agent group. A group shares configuration; a project attributes cost. An agent belongs to at most one of each, and they do not interact.

Creating one

POST/v1/projects
Shell
curl -s -X POST https://voice.sphoro.com/v1/projects \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Clinic",
    "monthly_budget": 50000,
    "over_budget": "refuse"
  }'
FieldTypeDescription
name
required
stringWhat you call it.
description
optional
stringYours.
monthly_budget
optional
numberThe ceiling for a calendar month. Omit for no ceiling — attribution without a limit, which is what most projects want.
over_budget
optional
stringWhat happens past the ceiling. Refusing new calls is the safe default; the alternative is to keep dialling and let the overrun be visible in analytics.
metadata
optional
objectYours.

Attributing work to it

Set project_id on the agent, and every call that agent takes or places is attributed there. A knowledge base can carry one too, so ingestion is billed with the work it serves.

Shell
curl -s -X PATCH https://voice.sphoro.com/v1/agents/$AGENT_ID \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id": "prj_6e2f90c1a4b73d85"}'

Going over budget

A call refused because its project is over budget ends with end_reason: over_budget — and inbound callers hear the busy line rather than silence.

A budget stops inbound calls too. That surprises people: a project that runs out mid-month stops answering the phone, not just stops dialling. On a support line that is usually not what anybody wanted. Either leave the budget off and watch analytics, or put the inbound line in its own project.

The endpoints

EndpointDoes
POST /v1/projectsCreate one.
GET /v1/projectsList them, with spend against budget.
GET /v1/projects/{id}Read one.
PATCH /v1/projects/{id}Change the budget or the name.
DELETE /v1/projects/{id}Remove it. Finished calls keep their attribution.
Shell
curl -s https://voice.sphoro.com/v1/projects \
  -H "Authorization: Bearer $SPHORO_API_KEY"

Slicing analytics by project

Every analytics query takes a project, which is the point of the whole feature: what did this client cost us this month, and how does that compare to last.

GET/v1/analytics/overview
Shell
curl -s "https://voice.sphoro.com/v1/analytics/overview?project_id=$PROJECT_ID&from=2026-09-01&to=2026-09-30" \
  -H "Authorization: Bearer $SPHORO_API_KEY"

See analytics.

How to divide them up

If you areA project per
An agency running calls for clientsClient. This is the case the feature exists for.
Running campaigns against your own listCampaign, so a month's spend is attributable to the thing that caused it.
One product with a support lineProbably nothing — one project, no budget, and watch analytics.