{"id":29152859,"url":"https://github.com/yannisalexiou/appstore-webhook-proxy","last_synced_at":"2025-07-01T01:04:55.085Z","repository":{"id":298790525,"uuid":"1001152419","full_name":"yannisalexiou/appstore-webhook-proxy","owner":"yannisalexiou","description":"App Store Webhook Proxy for Slack \u0026 MS Teams","archived":false,"fork":false,"pushed_at":"2025-06-26T10:05:17.000Z","size":219,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-26T11:19:01.861Z","etag":null,"topics":["app-store-connect","ios","microsoft-teams","nodejs","productivity","slack","slack-api","webhook"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yannisalexiou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-12T23:00:06.000Z","updated_at":"2025-06-26T10:01:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"4e3227ee-6ab9-41ad-b307-caea0bea0696","html_url":"https://github.com/yannisalexiou/appstore-webhook-proxy","commit_stats":null,"previous_names":["yannisalexiou/appstore-webhook-proxy"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/yannisalexiou/appstore-webhook-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannisalexiou%2Fappstore-webhook-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannisalexiou%2Fappstore-webhook-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannisalexiou%2Fappstore-webhook-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannisalexiou%2Fappstore-webhook-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yannisalexiou","download_url":"https://codeload.github.com/yannisalexiou/appstore-webhook-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannisalexiou%2Fappstore-webhook-proxy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262876870,"owners_count":23378139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-store-connect","ios","microsoft-teams","nodejs","productivity","slack","slack-api","webhook"],"created_at":"2025-07-01T01:03:12.819Z","updated_at":"2025-07-01T01:04:55.014Z","avatar_url":"https://github.com/yannisalexiou.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# App Store Webhook Proxy for Microsoft Teams \u0026 Slack\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Node.js](https://img.shields.io/badge/node-%3E%3D18.x-brightgreen)\n\n[![Docker Ready](https://img.shields.io/badge/docker-ready-blue)](https://hub.docker.com/r/yannisalexiou/appstore-webhook-proxy)\n[![Render Ready](https://img.shields.io/badge/Render-Ready-8A06FF?style=flat\u0026logo=render\u0026logoSize=auto)](https://render.com/deploy)\n[![Unraid Ready](https://img.shields.io/badge/Unraid-Ready-f15a2c?style=flat\u0026logo=unraid\u0026logoSize=auto)](https://forums.unraid.net/topic/191280-support-yannisalexiou-app-store-webhook-proxy/)\n\n![Slack Integration](https://img.shields.io/badge/slack-supported-4A154B?logo=slack\u0026logoColor=white)\n![MS Teams Integration](https://img.shields.io/badge/teams-supported-6264A7?logo=microsoft-teams\u0026logoColor=white)\n\n[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%E2%98%95-blue)](https://coff.ee/alexiou)\n\nThis project provides a simple, secure Node.js proxy to forward webhook events from **App Store Connect** to **Microsoft Teams** and/or **Slack**, including signature verification and platform-specific formatting.\n---\n\n## 🚀 Features\n\n- ✅ Verifies App Store webhook signatures using HMAC SHA-256\n- ✅ Forwards formatted messages to Microsoft Teams and Slack\n- ✅ Custom message templates per platform\n- ✅ Supports custom timezones for event timestamps\n- ✅ Error handling and logging\n- ✅ Dockerized and ready for deployment (e.g. Render, Railway)\n- ✅ One-click deployable to Render\n\n---\n\n## 📋 Prerequisites\n1. App Store Connect access with one of the following roles: **Account Holder**, **Admin**, or **App Manager** to create a webhook.\n2. A configured workspace in either: Microsoft Teams and/or Slack\n\n---\n\n## 📦 Installation Guides\nEnd-to-end simple installation guides, from installing the proxy to get the test message to MS Teams / Slack\n\n### 💬 Microsoft Teams\n![MS Teams Notification Screenshot](documentation/assets/TeamsAppStoreUpdateResponse.png)\n\n**📘 Step-by-step setup guide**: [Integrate App Store Webhooks with Microsoft Teams (Medium)](https://medium.com/p/af3c8c840c15)\n\n### 💬 Slack\n![Slack Notification Screenshot](documentation/assets/SlackAppStoreUpdateResponse.png)\n\n**📘 Step-by-step setup guide**: [Integrate App Store Webhooks with Slack (Medium)](https://medium.com/p/4785b8306c81)\n\n---\n\n## ✅ Supported Webhook Events\n- `appStoreVersionAppVersionStateUpdated`\n- `webhookPingCreated`\n\nUnknown events will still be delivered in raw JSON.\n\n---\n\n## 🔧 Proxy Setup Options\nHere you can find all the available options to run the proxy.\n\n⚠️ To make the proxy work, it must be accessible from the internet. In my Unraid setup, I use an NGINX reverse proxy. If you're not familiar with this, it's easier to use the [1. One-Click Render Deployment](#1-one-click-render-deployment) option, which provides a public domain automatically.\n\n**The incoming webhook should be sent to the path: `/appstore-webhook`.**\n\n### 1. One-Click Render Deployment\nClick below to deploy instantly to Render:\n\n[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy)\n\nMake sure to set the environment variables during setup [(Read the Environment Variables table below)](#%EF%B8%8F-environment-variables).\n\u003e Render automatically sets `NODE_ENV=production`\n\n### 2. Unraid Setup\nTo install via Unraid:\n\n1. Open the **Apps** tab in your Unraid dashboard.\n2. Search for:  \n   **`AppStore-Webhook-Proxy`**\n3. Click **Install** and configure the required environment variables.\n\n💬 **Need help or want to leave feedback?**  \nJoin the support thread in the [Unraid Community Forum](https://forums.unraid.net/topic/191280-support-yannisalexiou-app-store-webhook-proxy/).\n\n🎥 **Watch the setup walkthrough:**  \n[![Watch the video](https://img.youtube.com/vi/g_EBC1CdblE/0.jpg)](https://www.youtube.com/watch?v=g_EBC1CdblE)\n\n### 3. Docker Setup\nBuild and run using Docker:\n\n```bash\ndocker build -t appstore-webhook-proxy .\ndocker run -p 3000:3000 --env-file .env appstore-webhook-proxy\n```\n\n### 4. Manual Setup (Node.js)\nIf you'd like to run the app directly with Node.js:\n\n```bash\ngit clone https://github.com/yourusername/appstore-webhook-proxy.git\ncd appstore-webhook-proxy\nnpm install\n```\n\n---\n\n## ⚙️ Environment Variables\n\nCreate a `.env` file (or set variables directly in your cloud environment):\n\n| Variable            | Explanation                                                                                                                                                                                                 | Default Value |\n|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|\n| `SHARED_SECRET`     | **Required.** Secret used to verify incoming App Store Webhook requests. You define it when creating the webhook in App Store Connect, then set the same value here.\u003cbr\u003eSet it here: [App Store Webhooks Setup](https://appstoreconnect.apple.com/access/integrations/webhooks) | *(empty)*     |\n| `TEAMS_WEBHOOK_URL` | **Required if integrating with Microsoft Teams.** Webhook URL for sending notifications to Microsoft Teams. Leave empty if not used.\u003cbr\u003eExample: `https://your-teams.webhook.url`\u003cbr\u003eCreate it here: [Microsoft Teams Incoming Webhook Guide](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cdotnet) | *(empty)*     |\n| `SLACK_WEBHOOK_URL` | **Required if integrating with Slack.** Webhook URL for sending notifications to Slack. Leave empty if not used.\u003cbr\u003eExample: `https://hooks.slack.com/services/XXX/YYY/ZZZ`\u003cbr\u003eCreate it here: [Slack Webhook Guide](https://api.slack.com/messaging/webhooks) | *(empty)*     |\n| `APP_STORE_URL`     | *(Optional)* Public URL of your app on the App Store. Included in notifications to make it easier to access the app’s page.\u003cbr\u003eExample: `https://apps.apple.com/app/id123456789` | *(empty)*     |\n| `TIMEZONE`          | *(Optional)* Timezone used to format timestamps in messages. Use a valid [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), e.g. `Europe/Athens`. | `UTC`         |\n\n\n\n\nYou can also copy from the example:\n```bash\ncp .env.example .env\n```\n\n---\n\n## 🧪 Running Locally\n\n```bash\nnpm start\n```\nThen send a webhook POST to:\n```\nhttp://localhost:3000/appstore-webhook\n```\n\n---\n\n## 🔐 Usefull App Store Connect info:\n- When setting up the webhook in App Store Connect, Apple will ask for a **secret**. Use a string of your choice and set it in `SHARED_SECRET`.\n- Official docs:\n  - [Apple Webhook Notification Overview]()https://developer.apple.com/documentation/AppStoreConnectAPI/webhook-notifications\n  - [Configuring Webhook Notifications](https://developer.apple.com/documentation/appstoreconnectapi/configuring-webhook-notifications)\n  - [Webhook Permissions Guide](https://developer.apple.com/help/app-store-connect/manage-your-team/manage-webhooks)\n\n\n---\n\n## 📂 Project Structure\n\n```\n.\n├── app.js                 # Entry point\n├── routes/\n│   └── webhook.js         # Webhook handler\n├── utils/\n│   ├── eventTemplates.js  # Teams formatter\n│   ├── slackTemplates.js  # Slack formatter\n│   └── stateDescriptions.js\n├── services/\n│   ├── signatureVerifier.js\n│   ├── teamsNotifier.js\n│   └── slackNotifier.js\n├── middleware/\n│   ├── errorHandler.js\n│   └── logging.js\n├── Dockerfile\n├── render.yaml            # Render deploy spec\n├── .env.example\n├── .dockerignore\n├── .gitignore\n└── README.md\n```\n\n---\n\n## 💡 Contributing\n\nPRs and feedback welcome! You can help with:\n- More supported event types\n- Custom Slack/Teams formatting\n- Delivery logs and retry support\n\n---\n\n## 📝 License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannisalexiou%2Fappstore-webhook-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyannisalexiou%2Fappstore-webhook-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannisalexiou%2Fappstore-webhook-proxy/lists"}