Income Graph Developers

Costs and allocations

Attach a cost to the groups and streams it hits, and read back where every dollar of cost lands.

A cost is a node of its own. It reduces total profit, and its allocations say which groups and streams it applies to. In the app this is the Costs section, and the cost also shows up under each source it hits (“Costs hitting this source”).

The link is stored once, on the cost. Writing an allocation through the API is the same as choosing it in the app, and the app shows it on both sides.

An allocation

{ "targetId": "1", "mode": "percent", "value": 50 }

Overhead

Whatever no allocation claims is overhead. It still reduces profit, at the top level. A cost with no allocations ("allocations": [], or the field left out) is all overhead. Allocating a cost changes where it is shown, never how much there is, so summary.annual.fees and profit are the same either way.

If the allocations ask for more than the cost, for example a fixed amount larger than the cost, they are scaled down to fit and the summary reports what each one actually takes.

Example

A subscription stream, a hosting cost that applies half to it, and an accountant that is plain overhead:

curl -s -X POST https://api.incomegraph.net/v1/graphs \
  -H "Authorization: Bearer $INCOMEGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"SaaS","sources":[
    {"id":"1","type":"recurring","name":"Pro subscriptions","amount":29,"units":200,"period":"monthly","fees":[]},
    {"id":"2","type":"cost","name":"Hosting","parentId":null,"amount":400,"period":"monthly",
     "allocations":[{"targetId":"1","mode":"percent","value":50}]},
    {"id":"3","type":"cost","name":"Accountant","parentId":null,"amount":1200,"period":"annual","allocations":[]}]}'

In the response, summary.streams[0] reports annualAllocatedCosts (2,400) and annualNet (the stream’s revenue minus its fees and that allocation). Each entry in summary.costs reports allocatedAnnual, overheadAnnual and the resolved allocations, and summary.annual.overhead is the total no allocation claimed (here 2,400 from Hosting plus 1,200 from the Accountant).

Older graphs

A cost saved inside a group (parentId set, no allocations) counts as allocated 100% to that group, and the app converts it to an allocation the next time it opens the graph. New costs should be at the top level (parentId: null).

Tools

The MCP server takes the same fields in create_graph and update_graph.