Skip to main content
Hermes tells your system when a permanent change happens. Examples are a payout at its terminal state, a pay-in that credits your balance, and a completed conversion. For each change, Hermes sends an event to your webhook endpoint with an HTTP POST. One endpoint serves both Jenzy APIs. Events from the MWK API (/v1) and from the Multi-asset API (/v2) arrive at the same URL. The signature is the same. The api_version field tells you which API the data came from.

Register an endpoint

An org admin registers the endpoint in the Hermes portal, under Integration → Webhook endpoint. Each org has one HTTPS URL and one active endpoint. When you register an endpoint, Hermes makes a signing secret (whsec_…). Hermes shows the secret one time only. Keep the secret with your API key. If you replace the endpoint, Hermes makes a new secret. Deliveries that are already in progress continue with the old secret. So while you change the secret, verify each delivery against both secrets.

The event wrapper

Each delivery is a JSON POST with the same wrapper:
  • id — the key that you use to remove duplicates. Hermes delivers each event one time or more. The same event can arrive more than one time, and events can arrive in a different sequence. Process each id one time only, and ignore the repeats.
  • balance — a copy of your MWK balance from the time when Hermes prepared the event. Do not calculate a balance from webhooks, because events can arrive in a different sequence. GET /balance is the correct source. Only a /v1 delivery has this field.
  • data — the resource, with the same bytes as the equivalent read endpoint of the API that made the event.
  • api_version — present with the value "v2" on a delivery from the Multi-asset API. Absent on a delivery from the MWK API. Use this field to select the parser for data. A /v2 payout has amount and asset. A /v1 payout has amount_mwk. The event_type alone does not tell you which.
A delivery from the Multi-asset API looks like this:
If you use only the MWK API, ignore api_version. You never get a delivery that has it.

Event list

An org admin sets the floor for balance.low in the Hermes portal, under Integration → Balance floor. You can change the floor at any time. The floor is on your MWK balance only. There is no balance.low event on the Multi-asset API. Read GET /v2/balances instead. payout.* and collection.* events come from both APIs. On a /v2 delivery, data is the resource as GET /v2/payouts/{id} or GET /v2/collections/{id} shows it, and api_version is "v2".

Verify a signature

Each delivery has a Signature header. The header is the HMAC-SHA256 of the exact raw request body, with your signing secret as the key, in hexadecimal. There are no timestamp headers, and there is nothing more to put in order. Sign the bytes that you received. Then compare the two values in constant time.
Calculate the HMAC over the raw body bytes, before you parse the JSON. If you parse the JSON and write it again, the field sequence or the format changes. The signature then never agrees.
Node.js (Express)
While you change the secret, verify against the old secret and the new secret. Accept the delivery if one of the two agrees.

Compare your result against ours

The Hermes portal keeps a record of each delivery, under Portal → Deliveries. Open a row to see the exact bytes that Hermes sent, and the signature that Hermes calculated over those bytes. Use the screen when your signature does not agree. It shows you which of the two values is different, and it shows the bytes that your code must sign.
A reversal needs your attention, and your balance can be late. A payout.reversed or a collection.reversed event tells you that the provider took back money that already moved. Use the event as the correct signal, and let your balance catch up. A person in Jenzy operations posts the correction. For the full detail, see Payouts → How to learn the result and Pay-ins → Reversals.

Delivery rules

  • Only a 2xx response counts as a delivery. A redirect is a failure, and Hermes never follows one. Respond in less than 10 seconds, and do the real work after the response.
  • Hermes tries a failed delivery 5 more times across about 6 hours. The first tries are close together. Each try sends the same bytes, because Hermes made a copy of the payload at the time of the event. So the signature stays valid across all the tries.
  • After the last failed try, Hermes puts the delivery in a dead-letter queue and tells Jenzy operations. Hermes never sends it again automatically.
  • Portal → Deliveries lists each try against each of your endpoints, newest first.
  • If you missed events during an outage, ask Jenzy for a new delivery. Until then, compare your records against GET /payouts. A poll and a webhook give the same data, so the list endpoint is always a way to catch up.