MMeerPartners docs

Webhooks

MeerPartners inbound webhooks: deposit credit from a payment provider and MeerID identity events. Format, HMAC signature and idempotency by delivery id.

MeerPartners has inbound webhooks — the platform receives server-side notifications from trusted systems. All of them are signature-protected and idempotent.

There are no outbound event subscriptions yet

At this time the platform does not dispatch outbound webhooks for affiliate-program events (conversion approved, payout processed, etc.) — you cannot subscribe to them via the API. If you need to know the state of conversions, poll the data through the cabinet/read endpoints. This page describes only the inbound webhooks that the platform receives.

The deposit credit webhook

When a business tops up its escrow balance, the actual credit does not happen immediately: first a pending intent is created (POST /api/v1/merchant/deposit), and the money is credited via a server-side webhook from the payment provider.

POST/api/v1/merchant/deposit/webhook🔒 HMAC

This is an S2S endpoint: it is called by the trusted payment provider, not the browser. The signature is verified before the body is parsed.

Signature

X-Provider-Signature: <hex(HMAC_SHA256(secret, signing_string))>
X-Timestamp: 1717200000

The signing_string is the same scheme as for the postback:

{METHOD}\n{PATH}\n{X-Timestamp}\n{SHA256_hex(raw_body)}

The secret is the shared deposit-webhook secret configured by the operator (DEPOSIT_WEBHOOK_SECRET). Verification is constant-time.

Body

{
  "provider": "card",
  "provider_tx_id": "yk_2f9a1c",
  "deposit_intent_id": 88,
  "amount": "5000.00",
  "currency": "RUB",
  "status": "success"
}
FieldValue
providerThe provider identifier
provider_tx_idThe provider's transaction ID — the idempotency key
deposit_intent_idThe ID of the intent created at POST /api/v1/merchant/deposit
amountThe amount as a string
currencyThe currency, ISO-4217
statussuccess / failed / refunded

Idempotency and protection

  • Dedup by provider_tx_id: a redelivery will not credit the deposit twice.
  • Anti-replay: X-Timestamp within ±5 minutes; a replay of the same signature within the memory window is rejected. The memory window lives in Redis.
  • Fail-closed: if the webhook secret is not configured, the request is rejected (503) rather than let through. This closes the hole of an under-configured environment on a money endpoint.
CodeHTTPWhen
DEPOSIT_WEBHOOK_UNCONFIGURED503The webhook secret is not set (fail-closed)
DEPOSIT_WEBHOOK_SIGNATURE_INVALID401Missing headers, an invalid signature, a timestamp outside the window, or a replay
DEPOSIT_WEBHOOK_REPLAY_STORE_UNAVAILABLE503The replay-protection store is unavailable (fail-closed)
INVALID_PAYLOAD400Invalid JSON in the body

This is an operator-to-provider integration

The deposit webhook is configured on the platform side and the payment provider side. A business does not need to wire it up itself during normal operation — topping up the balance goes through the cabinet.

MeerID identity webhooks

Because sign-in goes through MeerID, the platform receives identity events from it in order to revoke access in time (a ban, an account deletion) and to synchronize merges. This is part of the SSO loop and is handled by the portal — you do not need to embed these into your own integration.

Back-channel logout

POST/api/v1/auth/meerid/backchannel-logout🔒

An OIDC Back-Channel Logout receiver. The body is application/x-www-form-urlencoded with a logout_token field. The token is verified against the JWKS (RS256: iss, aud, exp, the presence of a logout event, the absence of nonce). Based on the result, all of the user's sessions are revoked. An unknown subject → a no-op 200. An invalid token → LOGOUT_TOKEN_INVALID (401).

Identity webhook

POST/api/v1/auth/meerid/webhook🔒 HMAC

Accepts the account.merged and account.erased events.

  • HMAC-SHA256 over the raw body, using the string {timestamp}.{raw_body} and the MEERID_WEBHOOK_SECRET secret (constant-time).
  • Freshness |now − ts| ≤ 300 s (anti-replay), otherwise WEBHOOK_TIMESTAMP_STALE (401).
  • Dedup by the X-MeerID-Delivery header (at-least-once safe).
  • event_type is taken only from the signed body (headers are not covered by the signature).
  • An unknown event_type → a 200 no-op (forward-compatible).
  • If the secret is not set — fail-closed: any webhook is rejected.
EventPlatform action
account.mergedRebind meerid_sub; on a collision — revoke sessions and deactivate the old record
account.erasedDeactivation, clearing of the PII cache, revocation of all the user's sessions

More on the access-revocation model is in the engineering documentation Auth and security.

Webhook idempotency — the general principle

Any inbound webhook may arrive more than once (a retry after a timeout on the sender's side). The platform suppresses duplicates by the idempotency key:

WebhookDedup key
Depositprovider_tx_id
MeerID identityX-MeerID-Delivery

If you are writing your own sender system, send a stable delivery identifier and retry the request on failures: a duplicate will do no harm.

What's next