HTTP webhook

Send signed JSON payloads to any HTTPS endpoint. For custom backends, n8n, Make, Zapier, or your own infrastructure.

URL configuration

An HTTP webhook Destination will deliver signal data as a JSON POST to any HTTPS endpoint you control. The endpoint can be anything that accepts HTTP: a serverless function, an automation platform like n8n or Make, a Zapier webhook, or your own backend.

  1. 1

    Go to Destinations, then New destination

    In the Signalync dashboard, open Destinations in the sidebar and click New destination.
  2. 2

    Select HTTP webhook

    Choose HTTP webhook from the Destination type list.
  3. 3

    Enter the endpoint URL

    Paste your HTTPS endpoint URL. Always use HTTPS so signal data stays protected in transit.
  4. 4

    Add an HMAC secret (optional but recommended)

    Enter a secret string in the HMAC secret field. Signalync will use it to sign every request. Your endpoint can then verify the signature to confirm the payload came from Signalync and was not tampered with.
  5. 5

    Save

    Click Save. The Destination will then be ready to add to any Flow.

Request headers & retries

Signalync sends a standard set of headers with every HTTP webhook delivery.

Content-Typeapplication/json
X-Signalync-Signaturesha256=<hex>. Sent only when an HMAC secret is set on the Destination.

Your endpoint must respond with a 2xx status code promptly. Any non-2xx response or a connection timeout is treated as a failed delivery.

Retry behaviour

If a delivery fails, Signalync automatically retries it once a few seconds later. If the retry also fails, the delivery is marked as Failed in the Signals table, and you can inspect the HTTP status code returned by your endpoint in the delivery detail drawer.

HMAC signing

When you set an HMAC secret on the Destination, Signalync computes an HMAC-SHA256 signature over the raw request body and sends it in the X-Signalync-Signature header, prefixed with sha256=.

Your endpoint should verify this signature before processing the payload. Here is a Node.js example:

const crypto = require("crypto");

// rawBody must be the exact bytes received, do NOT parse as JSON first
const expected = crypto
  .createHmac("sha256", SECRET)
  .update(rawBody)
  .digest("hex");

const received = req.headers["x-signalync-signature"].replace("sha256=", "");

if (
  expected.length !== received.length ||
  !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))
) {
  return res.status(401).send("invalid signature");
}

// Safe to process now
const signal = JSON.parse(rawBody);
javascript
Sign the raw request body bytes, not a re-serialised JSON object. If your framework auto-parses the body before your middleware runs, buffer the raw bytes first, for example with Express: express.raw({ type: 'application/json' })

Verify the signature

If you set a secret on your destination, every request carries an X-Signalync-Signature header. Compute the HMAC over the raw request body and compare in constant time. Reject anything that does not match.

Node.js

const crypto = require("crypto");

function verifySignalync(rawBody, signatureHeader, secret) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
  return (
    signatureHeader.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected))
  );
}
javascript

Python

import hashlib
import hmac

def verify_signalync(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature_header, expected)
python
Delivery is retried once, 2 seconds after a non-2xx response. Respond 200 quickly and process asynchronously if your handler is slow.

Payload shape

Signalync posts one JSON object per delivery: the core resolved fields, a params map with every other parameter parsed from the original signal, and the delivery timestamp.

{
  "signalId": "550e8400-e29b-41d4-a716-446655440000",
  "symbol": "XAUUSD",
  "action": "buy",
  "volume": 0.1,
  "params": {
    "vol": "0.1",
    "sl_pips": "50",
    "comment": "MyStrategy"
  },
  "timestamp": "2026-07-17T10:30:00.000Z"
}
json

See the signal format reference for full field definitions, volume types, multi-TP syntax, and pending order fields.

Troubleshooting

Signature verification fails

The most common cause is signing a parsed (and re-serialised) JSON object instead of the raw body bytes. Whitespace and key order will differ after re-serialisation, producing a different HMAC. Buffer the raw bytes before your JSON parser runs. Also confirm the secret in your endpoint matches the secret stored on the Signalync Destination: both are case-sensitive.

Deliveries show as failed after retries

Open the signal in the Signals table and expand the delivery detail drawer. The HTTP status code returned by your endpoint is logged there. Common causes: the endpoint returning 4xx (check auth or payload parsing), the endpoint timing out (respond quickly and move slow work to an async queue), or the URL changed after the Destination was created.

Endpoint timeout errors

Signalync expects your endpoint to acknowledge receipt quickly. If your processing takes longer, respond immediately with 200 OK and handle the payload asynchronously in the background.

Duplicate deliveries

Retries can cause the same signal to be delivered more than once. Use the signalId field in the payload as an idempotency key: store it and skip processing if you have already seen it.