One destination per configured MT5 server. Registration returns 201; an existing destination returns 409. Store the generated secret when returned: it cannot be retrieved later. Supplied secrets are not echoed. An update affects the next attempt without a restart; an in-flight delivery may still use the old URL and key. Coordinate overlap with the receiver. Redirects are not followed.
Verify before parsing
The sender signs the exact bytes of the HTTP body. Parsing and re-encoding JSON first can break the signature. Example for trusted server-side Python code:event_id with a unique constraint in the same CRM transaction as the state update. Return 2xx only after commit (also for an already processed ID). Delivery is at least once, not ordered. Failed responses/timeouts retry with the same ID and body but a fresh signature timestamp. No destination means events stay pending; registration can deliver an older backlog.
The envelope has
event_id, type, UTC occurred_at and event-specific data. It contains no account passwords or bearer tokens.
Event payload examples
Each example below is a complete JSON body POSTed to your receiver. IDs, logins, timestamps and amounts are illustrative. The examples are formatted for readability; verify the signature against the original bytes, not this formatting.Subscription ended
Mark this allocation inactive. The notification identifies both MT5 logins.Account deleted
This closes the MAMX registration; it does not delete the MT5 user.Operation completed: account creation
FetchGET /api/v1/mamx/operations/{operation_id} for the result, including the new login. The webhook itself does not return credentials.
Operation completed: investor withdrawal
A withdrawal uses the same event type. Usedata.kind to distinguish it from account creation.
Operation rejected
Example: the existing MT5 account requested for registration was not found. Fetch the operation for the rejection reason.Operation needs review
The withdrawal outcome is uncertain. Do not issue another withdrawal.Fee debited
The investor has been charged. This is not confirmation that the payment account has been credited.Fee paid
The payment is confirmed.credit_batch_id is present for batch payments and omitted otherwise. This is the same fee as in the debit example, not a second charge.
Trade copy needs review
Identify the affected task and allocation when contacting the operator.Partial close needs review
data.event_id identifies the source close; it is not the webhook ID. Use the top-level event_id for delivery deduplication. remaining_volume can be null when the volume is unknown.

