Kling motion control price in usage.billable_amount_usd_micros
The Sume motion control submit response returns usage.billable_amount_usd_micros. Divide by 1,000,000 to log the reserve: 30 s is 4,725,000 micros, or $4.725.

Every Sume motion control submit returns usage.billable_amount_usd_micros in the response envelope. It is a whole number of millionths of a dollar, so divide by 1,000,000. For a 30-second reference it should be 4,725,000, which is $4.725, and for a 12-second reference 1,890,000, which is $1.89.
What is in the envelope
The standard submit envelope carries job.id, status_url, result_url, job.model and the usage object. For motion control job.model is always kling/3.0/motion-control, and usage.billable_amount_usd_micros is the amount reserved at admit. It is the same figure that your own formula should produce, so comparing them is a cheap test that you understood the price.
Log it at submit time
Store the number next to the job id the moment you get the response. Do not wait for the result, because the submit is the one time that the reserve and the declared length are both in your hand.
import os, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
"Idempotency-Key": "mc-demo-0001"}
body = {"image_url": "https://example.com/character.png",
"motion_video_url": "https://example.com/walk.mp4",
"duration_seconds": 12, "mode": "async"}
r = requests.post("https://api.sume.com/v1/kling/3.0/motion-control",
headers=H, json=body, timeout=60)
r.raise_for_status()
env = r.json()
micros = env["usage"]["billable_amount_usd_micros"]
print(env["job"]["id"], env["job"]["model"], micros / 1_000_000)
assert micros == 12 * 157_500, "price drifted from 0.1575/s"Micros for common lengths
The rate in micros is 157,500 per second, which is $0.1575. The assert above uses it, so a change in price shows up as a failed check in your own logs instead of a surprise in your invoice.
| duration_seconds | Micros | USD |
|---|---|---|
| 1 | 157500 | 0.1575 |
| 12 | 1890000 | 1.89 |
| 15 | 2362500 | 2.3625 |
| 30 | 4725000 | 4.725 |
Why integers help
Micros avoid float drift in a ledger. Add them as integers, convert to dollars only for display, and your totals match the invoice to the unit. A sum of floats such as 0.1575 x 12 can show a trailing digit in some languages, and an integer sum never does.
The figure is the reserve, not a promise of the final charge on a failed job. A job that fails is refunded, so keep the status next to the amount and count only the completed jobs in a spend report.
What to alert on
Two alerts are worth the five minutes. The first fires when micros does not equal ceil(duration_seconds) x 157,500, which means the price changed or your declared length is wrong. The second fires when the sum of reserves in a day goes past a limit that you set, since a loop that submits by mistake will do so quickly.
Keep the envelope's job.id with the micros so a finance question such as why one clip cost $4.725 can be answered by one lookup. The status route then tells you whether that job completed or was refunded.
Compared with the estimate
A pre-submit estimate and the envelope should agree. If you use a calculator such as the one in the cost post, run it, then compare its result to the value that came back, and log both. A match means your declared length and your formula are right. A mismatch is worth looking at at once, since it is cheaper to find a wrong length on the first job than on the hundredth.
Related posts
More in Developers
- Kling motion control webhook_url: a Python receiver that verifies
Send mode async plus webhook_url on a Kling motion control submit, then verify x-sume-webhook-signature (HMAC SHA-256 over timestamp.body) in Python.
- Compare 4 image models in one labelled 2x2 sheet with cost per tile
Send one prompt to four Sume image models, paste the results into a 2x2 Pillow sheet, and print each model id with its billed usage.cost on its own tile.
- Last frame of an Omni clip: fixing frame_time_out_of_range
Asking Sume video-frames for t equal to the clip length fails with frame_time_out_of_range. Take the last frame at duration minus a frame, in Python.
- Video-router image_url to /v1/videos frame_images, in Python
Map image_url, end_image_url and reference_image_urls from /v1/video-router/generate to frame_images and input_references on /v1/videos, with Python.
Written by Sume