Guild Embeds
Put a guild-owned Jukie library inside an authorized website or application. Jukie keeps media access scoped to one guild, measures active playback, and can send signed listening events back to your server.
How it works
- Your server authenticates the listener.Never place the shared signing secret in browser code.
- Your server creates a short-lived player token.The token identifies the external user, guild library, scopes, and session.
- Your page embeds the Jukie player.Jukie validates the token before listing or streaming any track.
- Jukie reports measured listening.Optional signed webhooks are idempotent and safe to retry.
Jukie configuration
Configure approved guilds, parent origins, and the optional listening webhook in Jukie's protected environment.
JUKIE_INTEGRATION_SHARED_SECRET=replace-with-a-long-random-secret
JUKIE_INTEGRATION_GUILD_IDS=123456789012345678
JUKIE_INTEGRATION_EMBED_ORIGINS=https://community.example
JUKIE_LISTENING_WEBHOOK_URL=https://community.example/api/jukie/listening
Create a signed token
Tokens use URL-safe base64 JSON and an HMAC-SHA256 signature. Generate a new jti for every player session and keep expiry short.
import base64, hashlib, hmac, json, secrets, time
now = int(time.time())
claims = {
"aud": "jukie-player",
"iss": "your-app",
"sub": "your-listener-id",
"guild_id": "123456789012345678",
"jti": secrets.token_urlsafe(24),
"iat": now,
"exp": now + 3600,
"scopes": ["player", "listening", "timeline_cues"],
"theme": "dark",
"library_label": "Community Radio",
"parent_origin": "https://community.example",
}
payload = base64.urlsafe_b64encode(
json.dumps(claims, separators=(",", ":"), sort_keys=True).encode()
).decode().rstrip("=")
signature = base64.urlsafe_b64encode(
hmac.new(SHARED_SECRET.encode(), payload.encode(), hashlib.sha256).digest()
).decode().rstrip("=")
token = f"{payload}.{signature}"
subYour stable listener identifier.guild_idThe single Jukie library this session may access.jtiA unique player session identifier.scopesMust contain player; add listening for progress and timeline_cues for real-time cue messages.themedark, rose, or light.Embed the player
Return the final URL from your authenticated backend, then assign it directly to the iframe. Do not place a protected redirect inside the frame.
<iframe
title="Community audio player"
src="https://jukie.app/integrations/v1/player?token=SIGNED_TOKEN"
allow="autoplay"
loading="lazy">
</iframe>
The player is responsive and supports native audio controls, track selection, shuffle, byte-range streaming, and the signed theme supplied by your server.
With timeline_cues, the player sends jukie.timeline-cue messages to the signed parent_origin as its audio clock crosses each neutral cue. Validate event.origin before acting. Use this channel for time-sensitive integrations; do not wait for listening-credit webhooks.
Media sources
Normal paid guilds use isolated hosted storage and retain uploads, subscription quotas, playlists, and Discord controls. Trusted self-hosted installations may additionally map a guild to an existing server folder.
JUKIE_GUILD_MEDIA_PATHS=123456789012345678=/srv/audio/community
Supported audio is indexed without copying it. Matching JSON sidecars may provide neutral audio_file and length_ms metadata; provider-specific fields are ignored. Remote services should be implemented as media-source adapters only when their supported API and licensing permit it.
Listening webhooks
When configured, Jukie sends compact JSON events signed over the exact request body. Verify X-Jukie-Signature with HMAC-SHA256 before accepting an event.
{
"provider": "jukie",
"external_user_id": "external-listener-id",
"event_id": "session-id:heartbeat-id",
"seconds": 15,
"track_id": "42"
}
Store event_id uniquely so retries cannot grant credit twice. Jukie measures heartbeat intervals server-side; consuming applications should never trust browser-submitted elapsed time.
Security checklist
- Authenticate listeners before issuing tokens.
- Use an unpredictable secret and rotate it deliberately.
- Allow only the guilds and parent origins your integration needs.
- Keep token lifetimes short and provide a visible disconnect control.
- Verify webhook signatures with a constant-time comparison.
- Reject expired, forged, replayed, or duplicate events.