- outgoing — the shop posts messages to your Discord channel (new order, daily report, announcement);
- incoming from payment providers (IPN) — the provider confirms a payment, and the platform verifies the signature and updates the order status. You don’t implement this yourself — a correctly configured payment method is enough.
ItemShop doesn’t currently send generic, signed HTTP webhooks to arbitrary URLs. To react to orders in your own system, poll
GET /orders/<shopId>?status=paid with an orders:read key (see API with a key), and use the plugin protocol to deliver items in game.Discord — setup
1
Create a webhook in Discord
Discord server settings → Integrations → Webhooks → new webhook on the chosen channel → copy its URL.
2
Paste the URL in the panel
Integrations → Discord → the Discord webhook URL field in the Connection section. The URL must start with
https://discord.com/api/webhooks/ (discordapp.com, canary.discord.com and ptb.discord.com are also allowed). Other URLs are rejected — this protects against SSRF.3
Enable message types and save
The “Send a notification for new orders” and “Send daily sales reports” toggles are independent. One Save integration button saves both tabs.
PUT /shops/<shopId> (requires shop:write): the fields discordWebhookUrl, discordWebhook (order-notification look) and discordWebhookDaily (daily-report look). API responses never return the full URL — you get hasDiscordWebhook and a masked tail discordWebhookUrlMasked instead.
When messages are sent
Voucher redemptions (free orders) are not counted in report amounts.
Look and placeholders
Each message type has its own title (up to 120 chars), bar colour, sender name (up to 80 chars), avatar URL and a message above the embed (up to 1500 chars). Fields come with sensible defaults; the avatar is optional. In the message above an order embed you can use:
In a daily report:
Placeholders from the two tables aren’t interchangeable. An unknown placeholder is left in the text unchanged.
Example payload
This is the request ItemShop sends to Discord after a new order (with the messagePlayer {nick} bought {product} for {amount}!). Default field labels are in Polish; you can rename them in the embed editor.
Delivery and retries
- Each message is a single
POSTattempt to Discord — there is no retry queue. - A failed send (e.g. deleted webhook, Discord rate limit) is logged and doesn’t block the order or its fulfillment.
- An empty webhook URL means no messages, regardless of the toggles.
Payment-provider webhooks
The payment provider sends its notification to a public platform endpoint:provider— the provider identifier (e.g.imojeTransfer,zen,paymentic);shopId— the shop the payment method belongs to;webhookSecret— the payment method’s secret, set during configuration.
Verification
The platform checks the secret in the URL and the provider’s signature over the original, unmodified request body before processing anything:
A forged webhook, wrong secret, mismatched provider or different shop →
401. Don’t modify notification bodies in a proxy — an altered body fails verification.
Statuses and response
After processing, the endpoint returns
200 with { "received": true }; providers treat 2xx as acknowledgement. Providers retry and send duplicates — the transition to paid is idempotent, so an order is marked paid (and the email and Discord notification are sent) exactly once.
Next
Payments
Configure providers and payment methods.
Plugin protocol
How a paid order reaches the game server.
API with a key
Polling orders from your own system.
Errors and limits
401, 409, 429 and retries.