A lost response on a 30 s Kling motion control submit: reuse the key

If a network timeout hides the reply to a 30-second Kling motion control submit, a new Idempotency-Key reserves $4.725 again. Reuse the key. Python retry loop.

4 min readSume
All posts

When the reply to a Kling 3.0 Motion Control submit is lost to a timeout, you do not know whether Sume admitted the job. Retry with the same Idempotency-Key, and the retry returns the original job instead of billing a second one. Retry with a new key, and a 30-second reference reserves $4.725 a second time, for $9.45 in total.

Sume's jobs documentation states the rule directly: retry the submit itself with the same key, and do not submit a new paid job for the same intent.

What a new key costs

Each admitted job reserves ceil(duration_seconds) times $0.1575. Two admitted jobs are two reservations, and both are captured if both complete.

Reservation after one lost response on a Kling motion control submit
Reference secondsOne jobRetry with a new keyExtra cost
8$1.26$2.52$1.26
15$2.3625$4.725$2.3625
30$4.725$9.45$4.725

Choose the key before the first send

Make the key from the intent, not from the attempt. A key that includes a random value or a clock reading is a new key on every retry, which defeats the purpose. Use the shot id, or a hash of the still URL, the motion URL, and the duration.

  • Same still, same motion video, same duration: same key.
  • A changed still or a changed motion video is a new intent: new key.
  • Keep the key in your own store with the job id once you have it.

A retry loop

This loop sends the same key on each attempt and stops on any HTTP answer, since an HTTP answer means Sume saw the request. It retries only when no answer arrived.

import json
import os
import time
import urllib.error
import urllib.request

URL = 'https://api.sume.com/v1/kling/3.0/motion-control'

def submit(body, key, attempts=3):
    data = json.dumps(body).encode()
    headers = {
        'Authorization': 'Bearer ' + os.environ['SUME_API_KEY'],
        'Content-Type': 'application/json',
        'Idempotency-Key': key,
    }
    for attempt in range(attempts):
        req = urllib.request.Request(URL, data, headers)
        try:
            with urllib.request.urlopen(req, timeout=20) as res:
                return json.load(res)
        except urllib.error.HTTPError as err:
            return {'http_status': err.code}
        except (urllib.error.URLError, TimeoutError):
            time.sleep(2 ** attempt)
    raise RuntimeError('no response; reuse the same key later: ' + key)

If you give up

If every attempt fails, do not mint a new key to try again. Wait, then call the same submit with the same key, or list your recent jobs and look for one with your metadata before you decide a job was never created. The wider rules, with a per-shot pattern, are in idempotency keys for AI video APIs.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume