Asana webhooks for Sume: handshake, compact payloads, task-keyed job

Asana needs the X-Hook-Secret echoed within 10 seconds and sends compact payloads. Fetch the task, then submit to Sume with a key built from the task gid.

4 min readSume
All posts

An Asana webhook does not hand you the task, only a compact event, so the handler has to fetch the task from Asana before it can build a Sume prompt. Complete the X-Hook-Secret handshake inside 10 seconds, ack every later delivery quickly, and submit to Sume with an Idempotency-Key made from the task gid so repeated events collapse into one job.

This post covers the Sume side and the delivery rules. It does not give signature code, because the Asana page names an HMAC-SHA256 X-Hook-Signature but does not say how the digest is encoded, and a verifier guessed from that would be wrong half the time.

Delivery rules worth designing around

The handshake: when you create the webhook, Asana sends a request with an X-Hook-Secret header, and your endpoint must echo it in the response with a 200 or 204 within 10 seconds, or creation fails. After that, events arrive with an X-Hook-Signature header computed from the body and that secret.

Asana retries failed deliveries for up to 24 hours and then deletes the webhook, and it sends a heartbeat roughly every 8 hours so you can tell the hook is alive. Payloads are described as compact, meaning an event names a resource and an action rather than carrying the full record. Hence the two-step flow: receive a change event for a task, call Asana for the task fields, then call Sume.

Asana webhook rules and their effect (read 2026-10-03)
Asana ruleValueDesign consequence
HandshakeEcho X-Hook-Secret with 200/204 in 10 secondsMake the endpoint cold-start safe
RetriesUp to 24 hours, then the webhook is deletedReturn 2xx fast; queue the work
HeartbeatAbout every 8 hoursTreat silence beyond that as a broken hook
PayloadCompact event, not the full taskFetch the task before prompting
RepeatsSeveral events can name the same taskKey the Sume job by task gid

Submitting from a task

After you have fetched the task, call Sume with a key tied to the task gid. If you also want a new job when the task's brief changes, add a short hash of the brief to the key; leave it out for one-image-per-task.

import os, requests

def submit_for_task(task_gid: str, name: str, notes: str) -> str:
    r = requests.post(
        "https://api.sume.com/v1/images",
        headers={
            "Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
            "Idempotency-Key": f"asana-{task_gid}",
        },
        json={"model": "sume/auto", "mode": "async",
              "prompt": f"{name}. {notes}"[:1500]},
        timeout=20,
    )
    r.raise_for_status()
    data = r.json()["data"]
    return data["job"]["id"]

Writing the result back

Do the write-back to Asana from your Sume webhook receiver, not from this function, and keep the task gid in your own table next to the Sume job id. The Sume event names the job, not the Asana task, and you want that lookup to be a database read, not a search. Because Asana deletes a hook that fails for 24 hours, keep the Asana endpoint thin and let your own queue absorb Sume and Asana API slowness.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume