← All code samples

Webhook → session only

Trigger a webhook and obtain session_id — without waiting for or downloading an artifact. Use this when another system owns the download step, or you only need the session id for logging or a follow-up API call.

Use client.aiden.trigger_webhook for a stateless trigger, then wait_for_webhook_session when the 202 body omits session_id. See Async webhook CI.

Step What the SDK does
1. Trigger POST /guild/api/v1/webhooks/trigger with webhook token
2. Session Use session_id from 202 when present; otherwise poll run detail

Runnable CLI

Run the step-by-step script without --download-report:

#!/usr/bin/env python3
"""Webhook trigger → read session_id (optional artifact download).

Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/webhook-session-artifact/

Usage:

  export WEBHOOK_TOKEN='sg_aios_…'
  python webhook-wait-session.py \\
    --base-url https://app.stackgen.com \\
    --api-token stackgen_… \\
    --org-id <project-uuid> \\
    --json-body \\
    --query 'P1 | checkout-api error rate above SLO'

  # Also download session-report.md when the workflow finishes:
  python webhook-wait-session.py … --download-report
"""

from __future__ import annotations

import argparse
import json
import sys

from stackgen import StackgenConfig, _http
from stackgen.aiden import sessions as session_helpers
from stackgen.errors import StackgenError


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--base-url", required=True)
    parser.add_argument("--api-token", required=True)
    parser.add_argument("--org-id", required=True)
    parser.add_argument("--webhook-token", default="", help="Or set WEBHOOK_TOKEN env")
    parser.add_argument("--query", default="Test webhook from stackgen-sdk example")
    parser.add_argument("--json-body", action="store_true")
    parser.add_argument("--download-report", action="store_true")
    parser.add_argument("--artifact-name", default="session-report.md")
    parser.add_argument("--output-path", default="session-report.md")
    parser.add_argument("--timeout-seconds", type=int, default=1800)
    parser.add_argument("--poll-interval-seconds", type=int, default=5)
    args = parser.parse_args()

    import os

    webhook_token = args.webhook_token or os.environ.get("WEBHOOK_TOKEN", "")
    if not webhook_token:
        print("error: set --webhook-token or WEBHOOK_TOKEN", file=sys.stderr)
        return 2

    config = StackgenConfig(
        base_url=args.base_url,
        api_token=args.api_token,
        webhook_token=webhook_token,
        org_id=args.org_id,
        artifact_name=args.artifact_name,
        output_path=args.output_path,
        timeout_seconds=args.timeout_seconds,
        poll_interval_seconds=args.poll_interval_seconds,
    )

    payload = (
        json.dumps({"message": args.query, "query": args.query})
        if args.json_body
        else args.query
    )
    content_type = "application/json" if args.json_body else "text/plain"

    url = f"{config.aiden_url()}/api/v1/webhooks/trigger{_http.query(config.org_id)}"
    print(f"POST {url} content_type={content_type}", file=sys.stderr)
    trigger = _http.request(
        url,
        config.webhook_token,
        method="POST",
        body=payload.encode("utf-8"),
        content_type=content_type,
    )
    if not isinstance(trigger, dict):
        raise StackgenError(f"unexpected trigger response: {trigger!r}")

    print(json.dumps(trigger, indent=2))

    session_id = _http.text(trigger.get("session_id"))
    if not session_id:
        raise StackgenError("trigger response missing session_id")

    print(f"session_id={session_id}", file=sys.stderr)

    if args.download_report:
        session_helpers.wait_for_artifact(config, session_id, args.artifact_name)
        path = session_helpers.download_artifact(
            config, session_id, args.artifact_name, args.output_path
        )
        print(f"output_path={path}", file=sys.stderr)

    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except StackgenError as exc:
        print(f"error: {exc}", file=sys.stderr)
        raise SystemExit(1)

Related: Webhook → session → artifact — adds artifact wait and download.