If a lip-sync job fails on Sume, is the reserved money refunded?

Yes. Sume reserves the price at admit, captures on completion and refunds on failure. For a 5-second H3 Max lip-sync at 768p the reservation is $0.50.

4 min readSume
All posts

Yes. For the MiniMax H3 Max lip-sync route, the API reserves the amount at admit, captures it when the job completes and refunds it if the job fails. A 5-second clip at 768p reserves $0.50, which is 5 x $0.08 x 1.25.

What the three steps mean

The price is ceil(duration_seconds) x the provider list rate per second at the chosen resolution x the 1.25 house margin. List rates are $0.05 at 480p, $0.08 at 768p and $0.16 at 1080p.

  • Reserve: when the job is accepted, the price is held against your balance.
  • Capture: if the job completes, the held amount is the charge.
  • Refund: if the job fails, the held amount is released.

Reservation by length

duration_seconds is a required field on this route and is the reservation basis. The API refuses a value outside 5 to 14.8 seconds with invalid_request and does not clamp it, because a clamped reservation would render a clip shorter than your audio.

H3 Max lip-sync reservation at 1.25 x list (Sume docs, read 2026-10-05)
ResolutionList per secondSume per second5 s clip14.8 s clip (ceil 15 s)
480p$0.05$0.0625$0.3125$0.9375
768p$0.08$0.10$0.50$1.50
1080p$0.16$0.20$1.00$3.00

What fails before the money moves

Several refusals happen at submit, so no job exists and nothing is reserved: audio that is not on Sume media (unsupported_audio_source), audio over 10 MB (audio_too_large), a duration outside the window, and a body that sets model, endpoint or provider_endpoint. Fix the request and send it again.

Check the outcome yourself

After you submit, poll GET /v1/jobs/{id}/status. The submit response carries usage.billable_amount_usd_micros, so you can compare the amount you expected with what the API reserved. This script submits one job and prints the reserved amount.

import json, os, urllib.request

body = {
    "avatar_handle": os.environ["AVATAR_HANDLE"],
    "audio_url": os.environ["AUDIO_URL"],
    "duration_seconds": 5.84,
    "resolution": "768p",
}
req = urllib.request.Request(
    "https://api.sume.com/v1/minimax/h3-max/lip-sync",
    data=json.dumps(body).encode(),
    method="POST",
    headers={
        "Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
        "Content-Type": "application/json",
        "Idempotency-Key": "lipsync-refund-check-001",
    },
)
with urllib.request.urlopen(req, timeout=30) as r:
    data = json.load(r)
print(data["job"]["id"], data["usage"]["billable_amount_usd_micros"])

What to do

Do not build your own refund logic. Submit with an Idempotency-Key, poll or use a webhook for the terminal state, and read the amount from the response. Retry a failed job with the same key only if it is an exact retry.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume