Check your image cost table against Sume /v1/images/models cost_usd

Read pricing lines from GET /v1/images/models/{id}/endpoints and compare cost_usd with your own table before a batch. Sume lines already include its margin.

5 min readSume
All posts

Before you run a large image batch, read the price from the API rather than from a spreadsheet. GET /v1/images/models/{model_id}/endpoints returns, for each endpoint, a pricing list with billable, unit and cost_usd. Sume's docs say those lines already include the Sume margin, so you pay cost_usd times n for n images. The Python script compares each line with the figure in your table and prints ok or DIFFERS.

What the endpoint returns

The list of models at GET /v1/images/models has a link to the endpoints route for each id. Each endpoint object names a provider slug and has a pricing array, for example one line with billable output_image, unit image and cost_usd 0.033 for a model in Sume's docs. The script flattens those lines.

Fields the script reads (Sume docs, read 2026-10-09)
FieldMeaning
endpoints[].provider_slugWhich backend the line belongs to
pricing[].billableWhat is counted, such as output_image
pricing[].unitUnit of the count, such as image
pricing[].cost_usdPrice per unit in USD, margin included
Your totalcost_usd x n images

A worked comparison

The sample table expects google/nano-banana-2.1 at 0.10 per image. That is the Sume list price for a 1K image. For 40 images the expected total is 40 x 0.10 = $4.00. If the endpoint prints a different cost_usd, the script says DIFFERS from 0.1, and you should find out whether the price changed or your table was for another size before you spend $4.00 or $40.00.

Prices for one model can differ by size. Nano Banana 2.1 is $0.075 at 0.5K, $0.10 at 1K, $0.15 at 2K and $0.20 at 4K in Sume's price list, so a table with one number per model is already a source of drift.

import json, os, urllib.request

EXPECTED = {"google/nano-banana-2.1": 0.10}  # USD per 1K image, from your own cost table

def endpoint_prices(model_id):
    req = urllib.request.Request(f"https://api.sume.com/v1/images/models/{model_id}/endpoints",
                                 headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"]})
    with urllib.request.urlopen(req) as r:
        endpoints = json.load(r)["endpoints"]
    return [(e["provider_slug"], line["billable"], line["unit"], line["cost_usd"])
            for e in endpoints for line in e["pricing"]]

for model, expected in EXPECTED.items():
    for slug, billable, unit, cost in endpoint_prices(model):
        flag = "ok" if abs(cost - expected) < 1e-9 else f"DIFFERS from {expected}"
        print(model, slug, billable, unit, cost, flag)

Make it a gate

The script exits cleanly even when a line differs. In a pipeline, change the print to a non-zero exit so a batch stops when the API and your table disagree. Compare with a small tolerance, as the sample does, because floating-point values from JSON can carry a trailing digit.

Billing for images is per image, not per token. Sume meters image models per image, and the token counts in the response are 0, so there is no token arithmetic to do.

A second use is catching a model alias. Sume accepts the bare Image Router ids as aliases for their org/slug equivalents, and retired ids run as their replacements, so a table keyed on an old id may price the wrong row. The endpoints route is read with the canonical id, which makes the comparison unambiguous.

Finally, record the date of the check with the result. A cost table that says it matched the API on a given day is much easier to trust at month-end than one with no history. Keep the expected prices in a file that you review with the finance owner, not in the script, so a change is a reviewed commit.

  • Run the check on the same key as the batch.
  • Store cost_usd in the job record.
  • Re-read prices on a schedule, not once.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume