bymundi API

n8n

Call the API from n8n and receive webhooks with signature checking.

Calling the API

  1. In n8n, Credentials → New → Header Auth: name Authorization, value Bearer bym_live_….
  2. Add an HTTP Request node: method and URL from the reference (for example POST https://api.bymundi.com/v1/trips), Authentication Generic → Header Auth with that credential, body JSON.
  3. For writes, add a header Idempotency-Key with the expression {{ $execution.id }}-{{ $runIndex }}, so an n8n retry never creates a duplicate.

List operations page with a cursor: enable Pagination, mode Update a parameter in each request, parameter cursor in the query = {{ $response.body.nextCursor }}, and stop when {{ $response.body.nextCursor === null }}.

Receiving webhooks

  1. Add a Webhook trigger node, method POST, and under Options turn on Raw Body. Copy its production URL.
  2. Create the endpoint with that URL (Webhooks guide) and keep the whsec_… secret in an n8n credential or variable.
  3. Add a Code node that verifies the signature before anything else. Self-hosted n8n must allow the built-in module: NODE_FUNCTION_ALLOW_BUILTIN=crypto.
const crypto = require("crypto");
const secret = $env.BYMUNDI_WEBHOOK_SECRET;
const h = $json.headers;
const raw = Buffer.from($binary.data.data, "base64").toString("utf8");
const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
const expected = crypto.createHmac("sha256", key).update(`${h["webhook-id"]}.${h["webhook-timestamp"]}.${raw}`).digest("base64");
const ok = h["webhook-signature"].split(" ").some((s) => s.split(",")[1] === expected);
if (!ok || Math.abs(Date.now() / 1000 - Number(h["webhook-timestamp"])) > 300) throw new Error("bad signature");
return [{ json: JSON.parse(raw) }];

The Webhook node answers 200 immediately by default, which is what bymundi wants.