Integrations
Custom webhooks
Send signed purchase JSON from any custom store or checkout backend into Analyse.
Custom webhooks let any store or checkout system send purchases into Analyse. Use this when you do not use Tebex or CraftingStore, or when your store already has its own backend that can send signed JSON after a payment completes.
Once connected, custom webhook purchases show up in Store analytics and can be attributed back to the player and their original Campaign.
How it works
- A player buys something on your store.
- Your store or backend sends a JSON
POSTto the Analyse custom webhook URL for that Server. - Analyse verifies the
X-Signatureheader using the webhook secret. - Analyse records the purchase, matches it to the player by username, and attributes it to the Campaign that originally brought them in.
Setup
- 1
Open the custom webhook integration in Analyse
Go to Settings → Integrations → Custom Webhook → Connect.
- 2
Generate the webhook secret
Analyse shows a unique webhook URL and a signing secret. Keep the secret private.
- 3
Add the URL to your store or backend
Send a POST request to the full URL Analyse gives you. It includes the Server's
projectId; do not remove that query parameter. - 4
Sign each request
Generate the signature from the exact JSON body you are sending and place it in the
X-Signatureheader. - 5
Send a test purchase
After Analyse accepts the first request, the integration's last sync time updates and the purchase appears in Store analytics.
Keep the body exact
The signature is calculated from the raw request body. If you sign one JSON string and send a differently formatted JSON string, the request returns 401.
Webhook URL
The URL looks like this:
https://www.analyse.net/api/webhooks/custom?projectId=SERVER_ID
Copy the real URL from Analyse. Each Server has its own projectId, so using the wrong URL sends the purchase to the wrong Server or returns 404.
Payload
Analyse expects JSON with three required fields:
| Field | Required | Type | Notes |
|---|---|---|---|
transaction_id | Yes | string | Unique ID from your store. Reusing the same value is treated as a duplicate purchase. |
username | Yes | string | Minecraft username to match against players on the Server. |
amount | Yes | number | Total purchase amount in the currency's normal unit, for example 9.99. |
currency | No | string | Defaults to USD when omitted. |
items | No | array | Line items shown in Store analytics. |
email | No | string | Stored on the purchase when present. |
timestamp | No | string | ISO timestamp for when the purchase happened. Defaults to the receive time. |
Example:
{"transaction_id": "order-123","username": "PlayerName","amount": 9.99,"currency": "USD","items": [{"name": "Diamond Rank","quantity": 1,"price": 9.99}],"email": "player@example.com","timestamp": "2026-03-27T12:00:00Z"}
If items is omitted, Analyse creates one item named Purchase with the purchase amount.
Each item should use this shape:
| Field | Required | Type | Notes |
|---|---|---|---|
name | Yes | string | Product or package name shown in Store analytics. |
price | Yes | number | Price for this line item. |
quantity | No | number | Defaults to 1 when omitted. |
Signing requests
Custom webhooks use HMAC-SHA256(SHA256(rawBody), webhookSecret).
That means:
- Turn the JSON payload into the exact string you will send.
- SHA-256 hash that string and encode the hash as lowercase hex.
- HMAC-SHA256 that hex hash with your webhook secret.
- Send the HMAC hex digest in the
X-Signatureheader.
Node.js example
const crypto = require("crypto");const webhookUrl = "https://www.analyse.net/api/webhooks/custom?projectId=SERVER_ID";const secret = "whsec_your_secret_here";const body = JSON.stringify({transaction_id: "order-123",username: "PlayerName",amount: 9.99,currency: "USD",items: [{ name: "Diamond Rank", quantity: 1, price: 9.99 }],});const bodyHash = crypto.createHash("sha256").update(body, "utf8").digest("hex");const signature = crypto.createHmac("sha256", secret).update(bodyHash).digest("hex");await fetch(webhookUrl, {method: "POST",headers: {"Content-Type": "application/json","X-Signature": signature,},body,});
cURL example
WEBHOOK_URL="https://www.analyse.net/api/webhooks/custom?projectId=SERVER_ID"WEBHOOK_SECRET="whsec_your_secret_here"BODY='{"transaction_id":"order-123","username":"PlayerName","amount":9.99,"currency":"USD"}'BODY_HASH=$(printf "%s" "$BODY" | shasum -a 256 | cut -d " " -f1)SIGNATURE=$(printf "%s" "$BODY_HASH" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | cut -d " " -f2)curl -X POST "$WEBHOOK_URL" \-H "Content-Type: application/json" \-H "X-Signature: $SIGNATURE" \-d "$BODY"
Responses
| Status | Meaning |
|---|---|
200 | Purchase accepted, or the same transaction_id was already processed. |
400 | Missing projectId, invalid JSON, missing required fields, or invalid amount. |
401 | Signature does not match the body and secret. |
404 | Custom webhook integration is not enabled for that Server. |
Amounts must be finite, non-negative numbers. Analyse rejects unusually large values above 1000000 to prevent accidental bad data.
How players get matched
Analyse matches the purchase to a player by username case-insensitively. If that player has joined the Server before, the purchase is linked to their player record and inherits their original Campaign attribution.
If no player matches, the purchase is still stored at the Server level and contributes to Store totals, but it is not attributed to a player or Campaign.
Duplicates and refunds
Custom webhooks currently create completed purchases only. Sending the same transaction_id again is safe; Analyse treats it as already processed and does not double-count revenue.
Refunds and chargebacks are not currently handled by the custom webhook endpoint. If your store needs full refund automation, use the Tebex integration where possible.
Rotating the secret
If the secret leaks, open Settings → Integrations → Custom Webhook and regenerate it. Analyse starts rejecting requests signed with the old secret immediately, so update your store or backend before sending more purchases.
Related
- Connect your store for the high-level setup options
- Store analytics for where purchases appear
- Revenue for attribution and ROI reporting