Destinations
Destinations define where your webhooks are forwarded. Juice Machine supports Slack, Discord, Microsoft Teams, email, PagerDuty, Telegram, and generic HTTP destinations. You can add more than one per app — for example, route to a Slack channel for the team plus a generic webhook for your own back-end.
Creating a Destination
- Navigate to your app in the dashboard
- Click Destinations
- Click New Destination
- Choose the destination type
- Enter the channel's settings (a webhook URL, email address, routing key, etc. depending on the type)
- Optionally untick any event types you don't want delivered
- Click Create Destination
Destination Types
Slack
Send formatted messages to Slack channels via the Juice Machine Slack app.
- From your app's dashboard, create a new destination and pick Slack as the channel type
- Click Add to Slack. You'll be redirected to Slack to authorise the Juice Machine app on your workspace
- Back in Juice Machine, pick the channel the bot should post to from the dropdown
- Public channels work immediately. For a private channel, run
/invite @juice-machinein Slack first so the bot can post there
Each Slack message includes:
- A header with the app name and App Store icon
- Event type, version/build number, status, and platform
- Color-coded category bar (subscription events, build state, etc.)
Re-installing later (e.g. moving to a different workspace) cleanly replaces the stored OAuth token. Existing channels you'd already picked stay selected as long as the bot still has access.
Discord
Post messages to a Discord channel via a server webhook.
- In Discord, open your server settings
- Go to Integrations → Webhooks → New Webhook
- Pick the channel to post into and copy the webhook URL
- Paste it as the destination URL in Juice Machine
The message will appear in Discord as if it were sent by the app itself (using its name and App Store icon as the avatar). Each message is a rich embed with status fields, a colour-coded category bar, and a context line for important events.
Send a formatted HTML email summarising the event to a single address. Useful for ops mailing lists, support queues, or anyone who lives in their inbox rather than a chat tool.
- Create a new destination and pick Email as the channel type
- Enter the recipient's email address
- Save and click Send Test to verify delivery
Each email subject is [Juice Machine] <app name> — <event title>,
so mail clients thread similar events together cleanly. Both an HTML
body and a plain-text fallback are sent. Messages come from
notification@juicemachine.net — allowlist
this address if your mail server filters unknown senders.
Microsoft Teams
Send notifications to Microsoft Teams channels.
- In Teams, right-click the channel where you want notifications and choose Workflows
- Pick the template "Post to a channel when a webhook request is received"
- Copy the generated webhook URL (legacy Office 365 connector URLs also work)
- Paste it as the destination URL in Juice Machine
Notifications are posted as Adaptive Cards with the same labelled fields as the other channels.
Generic Webhook
POST a JSON representation of the event to any HTTPS URL you control. Useful for your own back-end services, automation tools like Zapier or n8n, or a webhook receiver under your control.
- Create a new destination and pick Generic Webhook as the channel type
- Enter the HTTPS URL you want events POSTed to
- Save and click Send Test to verify delivery
The request body is a versioned JSON object:
{
"schema_version": 1,
"event": {
"id": 64,
"apple_event_id": "938f216c-…",
"event_type": "ONE_TIME_CHARGE",
"human_event_type": "One-Time Charge",
"received_at": "2026-05-18T13:17:17Z",
"environment": "Sandbox"
},
"app": { "id": 2, "name": "Simon's IAP Test", "bundle_id": "com.simonmaddox.IAPTest" },
"enriched_data": {
"app_name": "Simon's IAP Test App",
"product_name": "Small Tip",
"product_id": "com.simonmaddox.iaptest.smalltip",
"price_milliunits": 990,
"currency": "GBP",
"transaction_type": "Consumable",
"transaction_id": "2000001172484708"
},
"payload": { /* raw Apple payload, including signedTransactionInfo JWS */ }
}
Each request also carries these headers for routing without parsing the body:
X-JuiceMachine-Event: the Apple event type (e.g.DID_RENEW)X-JuiceMachine-Schema-Version: the payload schema version (currently1)X-JuiceMachine-Signature:sha256=<hex HMAC-SHA256 of the raw body>, keyed with the signing secret shown on the destination's page — see Authentication for how to verify itUser-Agent: JuiceMachine/1.0 (+https://juicemachine.net)
Receivers should return a 2xx status to mark the delivery as successful. Non-2xx responses (or transport errors) are recorded on the delivery row and retried with exponential backoff.
Customer user fields in notifications
If your app sets appAccountToken on StoreKit purchases and you configure a customer user lookup URL on the app, every destination listed above automatically picks up the returned user fields and renders them in its native shape — Slack as a 2-column section with action buttons, Teams as a FactSet, Discord as embed author + fields, email as a boxed customer table, PagerDuty as custom_details + links, Telegram as an HTML stanza, and the generic webhook as an enriched_user key on the JSON payload. No per-destination configuration needed.
Destination Settings
Enabled/Disabled
You can disable a destination to stop sending webhooks to it. This is useful for:
- Temporarily pausing notifications
- Debugging without affecting other destinations
- Maintaining inactive destinations for future use
Event Filters
By default each destination receives every event for its app — including any event types Apple introduces in the future. You can optionally restrict it to a subset (e.g. only subscription events, or only TestFlight feedback). Set filters when creating or editing the destination.
Common type + subtype combinations (e.g. "Auto-Renew Disabled", which is
DID_CHANGE_RENEWAL_STATUS:AUTO_RENEW_DISABLED) are listed as
their own checkboxes and controlled independently of their base type.
Unticking a base type (e.g. DID_RENEW) also stops delivery
of any of its subtype variants that aren't listed separately (such as
DID_RENEW:BILLING_RECOVERY).
Testing Destinations
Each destination has a Send Test button that sends a sample webhook to verify your configuration:
- Go to your destination's detail page
- Click Send Test
- Check your destination (Slack, Discord, etc.) for the test message
Test webhooks use a sample payload that mimics a real App Store Connect event.
Delivery Status
Each webhook delivery is tracked with one of these statuses:
| Status | Description |
|---|---|
| Pending | Webhook is queued for delivery |
| Delivered | Successfully delivered (2xx response) |
| Failed | Delivery failed — retried automatically until the retry limit is reached |
Deliveries are also re-checked against your plan at send time: if your team's plan no longer includes a destination's channel (e.g. after a downgrade), the delivery fails with an explanatory error instead of being sent. Upgrade the plan or switch the destination to an included channel.
Retrying Failed Deliveries
If a delivery fails, Juice Machine automatically retries with exponential backoff:
- 1st retry: 1 minute
- 2nd retry: 4 minutes
- 3rd retry: 16 minutes
- 4th retry: 64 minutes (~1 hour)
- 5th retry: 256 minutes (~4 hours)
You can also manually retry a failed delivery from the delivery detail page.