Webhooks & Events

Configure real-time notifications for asset uploads, download status changes, and community interactions on your SoundScape projects.

Event Types

SoundScape fires webhook events whenever a configured activity occurs in your studio workspace. Each event delivers a structured JSON payload to the endpoint URL you register in your project settings.

asset.uploaded

New Asset Uploaded

Triggered when a sound file is successfully ingested into your library. Includes file metadata, audio fingerprint hash, and upload timestamp. Fires once per asset — retries are not sent for duplicate uploads of the same file.

asset.status_changed

Download Status Update

Sent when a licensed download transitions between states: queuedprocessingready or failed. Useful for tracking batch-export pipelines or notifying your CI/CD when assets are ready for consumption.

community.like_added

Community Like

Fired when another SoundScape user likes a sound in your public collection. The payload includes the liker's public profile slug and the liked asset ID. Rate-limited to 60 events per minute per webhook endpoint.

community.comment_posted

Community Comment

Triggered when a user posts a comment on one of your sounds. Contains the comment body, author slug, and a moderation flag. Comments flagged for review include "moderation": true in the payload.

license.purchase_completed

License Purchase

Sent after a third-party buyer completes a license transaction for your asset. Includes the license tier (Standard, Extended, or Source), buyer organization slug, and transaction reference. Always delivered within 5 seconds of payment confirmation.

project.export_finished

Project Export Complete

Fires when a multi-track project export finishes rendering. The payload lists all rendered stems, their formats (WAV, OGG, MP3), and a short-lived download URL valid for 24 hours. Ideal for automating asset handoff to your game engine.

Payload Examples

Every webhook request uses POST with Content-Type: application/json. The body follows a consistent envelope structure: event, timestamp, webhook_id, and data.

asset.uploaded

{
  "event": "asset.uploaded",
  "timestamp": "2025-06-12T14:32:07Z",
  "webhook_id": "whk_8f3n2m9x1v",
  "data": {
    "asset_id": "snd_7d4k2p9q",
    "filename": "metal_impact_heavy_01.wav",
    "duration_sec": 1.84,
    "sample_rate_hz": 48000,
    "bit_depth": 24,
    "channels": 2,
    "fingerprint_hash": "sha256:a3f8c91e7b2d4f06",
    "upload_by": "user_marcus_renner",
    "project_id": "prj_soundscape_indie_rpg"
  }
}

asset.status_changed

{
  "event": "asset.status_changed",
  "timestamp": "2025-06-12T14:35:41Z",
  "webhook_id": "whk_8f3n2m9x1v",
  "data": {
    "asset_id": "snd_7d4k2p9q",
    "previous_status": "processing",
    "current_status": "ready",
    "format": "wav",
    "file_size_bytes": 1728000,
    "download_url": "https://cdn.soundscape.dev/dl/snd_7d4k2p9q?token=eyJhbG...",
    "expires_at": "2025-06-13T14:35:41Z"
  }
}

community.comment_posted

{
  "event": "community.comment_posted",
  "timestamp": "2025-06-12T18:11:22Z",
  "webhook_id": "whk_8f3n2m9x1v",
  "data": {
    "comment_id": "cmt_2x7w4n1k",
    "asset_id": "snd_9r1m5t8j",
    "author_slug": "elara_audio_design",
    "body": "Perfect for the boss fight cue — the low-end rumble sits really well under dialogue.",
    "moderation": false,
    "project_id": "prj_soundscape_indie_rpg"
  }
}

license.purchase_completed

{
  "event": "license.purchase_completed",
  "timestamp": "2025-06-13T09:47:55Z",
  "webhook_id": "whk_8f3n2m9x1v",
  "data": {
    "transaction_ref": "txn_4p8h2v6b",
    "asset_id": "snd_3k9c7w1n",
    "license_tier": "Extended",
    "buyer_slug": "studio_nocturn_games",
    "buyer_org_id": "org_nocturn_2024",
    "amount_cents": 4900,
    "currency": "USD",
    "project_id": "prj_soundscape_indie_rpg"
  }
}

Verification

Every webhook request includes an X-SoundScape-Signature header so you can verify the payload originated from SoundScape and has not been tampered with.

The signature is an HMAC-SHA256 digest of the raw request body, computed with your webhook secret. The secret is visible in your project settings under Integrations → Webhooks → Show Secret. Treat it like an API key — never commit it to public repositories.

Header format:

X-SoundScape-Signature: t=1718210527,v1=a8f3c2d1e9b7406f5a3c8d2e1b9f7a4c6d8e2f0a1b3c5d7e9f1a3b5c7d9e1f3

The header contains a timestamp (t) and the hex-encoded signature (v1). Reject requests where the timestamp is more than 5 minutes older than your server clock to prevent replay attacks.

Verification steps:

1. Read the raw request body as a string.
2. Extract the timestamp from X-SoundScape-Signature.
3. Reject if |now - timestamp| > 300 seconds.
4. Compute HMAC-SHA256(raw_body, webhook_secret).
5. Compare your computed digest with the v1 value using constant-time comparison.
6. Return HTTP 200 within 3 seconds to acknowledge receipt.

Python example:

import hashlib
import hmac
import time

def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    # Parse timestamp and signature
    parts = dict(item.split("=") for item in signature_header.split(","))
    ts = int(parts["t"])
    sig = parts["v1"]

    # Timestamp check: reject if older than 5 minutes
    if abs(time.time() - ts) > 300:
        return False

    # Compute HMAC-SHA256
    computed = hmac.new(
        secret.encode("utf-8"),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    # Constant-time comparison
    return hmac.compare_digest(computed, sig)

If verification fails, respond with HTTP 401. SoundScape will retry delivery up to 3 times with exponential backoff (1 minute, 5 minutes, 15 minutes). After all retries are exhausted, the webhook is disabled and you receive an email alert at the project lead's address.

For local development, use ngrok or localtunnel to expose a temporary HTTPS endpoint. SoundScape only accepts https:// webhook URLs — http:// endpoints are rejected at registration time.