Slack slash command for music: 3 s ack, 5 replies in 30 min
A Slack command must be acknowledged in 3 s; response_url then allows 5 replies in 30 min. Start the Sume music job in webhook mode and reply when it lands.

For a Slack slash command that makes a music track, answer Slack inside 3 seconds, start the Sume job in webhook mode, and reply later through the response_url. Slack's docs say that URL can be used up to 5 times within 30 minutes of the payload. A Sume Music Router job is accepted immediately, so the two clocks fit if you spend replies on purpose.
The two clocks
Slack's page on interactions states two rules. Your app must send an HTTP 200 within 3 seconds of receiving the payload, or the user sees an error. Delayed responses go to the response_url, which accepts up to 5 responses within 30 minutes.
| Clock | Limit | What it means for a music command |
|---|---|---|
| Slack acknowledgement | 200 OK within 3 seconds | Never wait for the track inside the command handler |
| Slack response_url | 5 responses, 30 minutes | One working reply, one result, three spare for retries or errors |
| Sume sync wait | At most 30 seconds, then poll | Do not use sync for a song; use webhook mode |
| Sume webhook delivery | Up to 10 attempts, 30 s apart, 10 s timeout | Return 2xx fast, then post to Slack |
The flow
The command handler does three things, then returns 200 with no body or a short working line. It derives an Idempotency-Key from the command, starts the job, and stores job_id next to the response_url. The Sume webhook receiver, which is a different route, looks up the response_url by job_id and posts the result.
The Music Router charges a fixed $0.125 per generation, and POST /v1/music-router/generate has no duration field, so put the length in the prompt text, for example a 30-second track.
import hashlib, json, os, urllib.request
JOBS = {} # job_id -> response_url (use a real store)
def start_track(prompt, response_url, receiver_url):
key = "slack-" + hashlib.sha256((response_url + prompt).encode()).hexdigest()[:32]
body = {"prompt": prompt, "mode": "webhook", "webhook_url": receiver_url}
req = urllib.request.Request(
"https://api.sume.com/v1/music-router/generate",
data=json.dumps(body).encode(),
headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
"Content-Type": "application/json", "Idempotency-Key": key})
with urllib.request.urlopen(req, timeout=10) as r:
job_id = json.load(r)["request_id"]
JOBS[job_id] = response_url
return job_id
def on_sume_event(event):
url = JOBS.get(event["job_id"])
if not url:
return
arts = (event.get("payload") or {}).get("artifacts") or []
audio = next((a["url"] for a in arts if a.get("type") == "audio"), None)
text = audio or "The track failed. Nothing was created."
req = urllib.request.Request(url, data=json.dumps({"text": text}).encode(),
headers={"Content-Type": "application/json"})
urllib.request.urlopen(req, timeout=10).read()Spend the five replies deliberately
Reply 1 is the working message. Reply 2 is the result. Keep the remaining three for a failure notice, a retry that the user asks for, and one spare. If the job takes longer than 30 minutes from the original command, the response_url is dead and you need a normal Slack message to a channel instead.
Limits
Verify Sume's signature on the receiver before you touch the store: the header is x-sume-webhook-signature: sume-v1=<hex> over <timestamp>.<raw_body>. Do not put a non-empty negative_prompt in the request, because Music Router returns 400 for it. The response_url is a credential for that channel, so keep it out of logs.
Sources
Related posts
More in Integrations
- Slack Workflow webhook trigger: flatten a Sume result, no nested JSON
Slack's webhook-started workflows take up to 20 flat variables and 1 request per second. Flatten Sume's nested artifacts into plain text values before you post.
- Snapchat monetization advice: closed captions, 30 s, and Sume
Snapchat's monetization page says videos need 30 seconds for revenue and recommends closed captions. Burn captions with Sume video captions at $0.20 per job.
- Snapchat Spotlight Post button needs 5 seconds: probe and trim
Snapchat says the Post button for Spotlight appears when a video is at least 5 seconds. Probe a clip's duration with Sume, trim the dead lead-in, and re-check.
- Tally webhook to a Sume music job: verify, dedupe, return 200 fast
Tally signs with base64 HMAC-SHA256, waits 10 s and retries up to a day. Verify the signature, use eventId as the Idempotency-Key, then start the Sume job.
Written by Sume