Webhooks Overview

Webhooks allow MeSomb to notify your application when an important event happens in your account.

Instead of repeatedly calling the MeSomb API to check whether a payment has changed, your application can expose a webhook endpoint. MeSomb will send an HTTP request to that endpoint whenever a subscribed event occurs.

Typical webhook use cases include:

  • confirming that a payment transaction succeeded;
  • updating an order after a checkout session is completed;
  • releasing goods or services after a secure payment is funded;
  • synchronizing payment status with your internal system;
  • receiving dispute, refund, payout, or account lifecycle notifications.

How webhooks work

A webhook is an HTTP POST request sent by MeSomb to a URL that you configure.

Example flow:

flowchart TD A[Customer completes payment] --> B[MeSomb creates an event] B --> C[MeSomb sends a webhook to your endpoint] C --> D[Your server verifies the signature] D --> E[Your server processes the event] E --> F[Your server returns a 2xx response]

Example webhook endpoint URL:

<span><span style="color: undefined">https://example.com/webhooks/mesomb</span></span>
<span><span style="color: undefined"></span></span>

Your endpoint must be publicly reachable over HTTPS.

Webhook event structure

All MeSomb webhook events use the same top-level structure.

<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;id&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;adbbf6bd-1746-4545-a3ce-8b153a7a31b2&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;object_type&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;payment&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;event_type&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;payment.succeeded&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;api_version&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;2026-05-01&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;created_at&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;2026-05-07T22:15:30Z&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;livemode&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">&quot;object&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;id&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;txn_01HX9K7A1R6F8MZK2Q9V7N4P5B&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;object&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;payment_transaction&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;status&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;succeeded&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;amount&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">15000</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;currency&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;XAF&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;reference&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;ORDER-10045&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">&quot;previous_attributes&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;status&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;pending&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Top-level fields

FieldTypeDescription
idstringUnique ID of the webhook event. Use this for deduplication.
object_typestringAlways event.
event_typestringName of the event, for example payment.success.
api_versionstringMeSomb API version used for this event payload.
created_atstringDate and time when the event was created, in ISO 8601 UTC format.
livemodebooleantrue for live events, false for test events.
data.objectobjectSnapshot of the resource affected by the event.
data.previous_attributesobjectPrevious values for fields that changed, when available.

Event naming convention

MeSomb event names follow this format:

<span><span style="color: undefined">domain.resource.action</span></span>
<span><span style="color: undefined"></span></span>

Examples:

<span><span style="color: undefined">payment.transaction.succeeded</span></span>
<span><span style="color: undefined">checkout.session.completed</span></span>
<span><span style="color: undefined">secure_payment.transaction.released</span></span>
<span><span style="color: undefined">dispute.created</span></span>
<span><span style="color: undefined">payout.paid</span></span>
<span><span style="color: undefined"></span></span>

The event name should be used by your application to decide how to process the webhook.

Example:

<span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> event</span><span style="color: var(--shiki-token-punctuation)">[</span><span style="color: var(--shiki-token-string-expression)">&quot;type&quot;</span><span style="color: var(--shiki-token-punctuation)">]</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;payment.transaction.succeeded&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-function)">handle_successful_payment</span><span style="color: var(--shiki-token-punctuation)">(event[</span><span style="color: var(--shiki-token-string-expression)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">][</span><span style="color: var(--shiki-token-string-expression)">&quot;object&quot;</span><span style="color: var(--shiki-token-punctuation)">])</span></span>
<span><span style="color: var(--shiki-token-keyword)">elif</span><span style="color: var(--shiki-color-text)"> event</span><span style="color: var(--shiki-token-punctuation)">[</span><span style="color: var(--shiki-token-string-expression)">&quot;type&quot;</span><span style="color: var(--shiki-token-punctuation)">]</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;checkout.session.completed&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-function)">handle_completed_checkout</span><span style="color: var(--shiki-token-punctuation)">(event[</span><span style="color: var(--shiki-token-string-expression)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">][</span><span style="color: var(--shiki-token-string-expression)">&quot;object&quot;</span><span style="color: var(--shiki-token-punctuation)">])</span></span>
<span></span>

Webhook response requirements

Your webhook endpoint should return a 2xx HTTP status code when the event has been successfully received.

Recommended responses:

<span><span style="color: undefined">HTTP/1.1 200 OK</span></span>
<span><span style="color: undefined"></span></span>

or:

<span><span style="color: undefined">HTTP/1.1 204 No Content</span></span>
<span><span style="color: undefined"></span></span>

Any non-2xx response may cause MeSomb to retry the webhook.

Retry behavior

MeSomb may retry webhook delivery when your endpoint does not return a 2xx response.

Retries can happen when:

  • your endpoint returns 4xx or 5xx;
  • your endpoint times out;
  • the network connection fails;
  • MeSomb cannot confirm that your server received the event.

Your webhook integration must be idempotent because the same event can be delivered more than once.

Recommended retry policy:

<span><span style="color: undefined">Automatic retry window: up to 72 hours</span></span>
<span><span style="color: undefined">Manual replay window: up to 90 days</span></span>
<span><span style="color: undefined">Full event history retention: 90 days</span></span>
<span><span style="color: undefined">Lightweight metadata retention: up to 2 years</span></span>
<span><span style="color: undefined"></span></span>

Duplicate events and idempotency

Webhook events can be delivered more than once.

Always use the event ID to detect duplicate events:

<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;id&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;adbbf6bd-1746-4545-a3ce-8b153a7a31b2&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Recommended behavior:

  1. Receive the webhook.
  2. Verify the signature.
  3. Check whether the event ID has already been processed.
  4. If already processed, return 200 OK without running the business action again.
  5. If not processed, process the event and store the event ID.

Webhook signature verification

Every webhook request sent by MeSomb is signed.

Your server should verify the X-MeSomb-Webhook-Signature header before processing the event.

Webhook signature verification protects your integration against fake or modified webhook requests.

Read the full guide in: Verifying webhook signatures.

Security recommendations

Before using webhooks in production:

  • use HTTPS for your webhook endpoint;
  • verify the X-MeSomb-Webhook-Signature header;
  • use the raw request body for signature verification;
  • reject old timestamps;
  • store processed event IDs for deduplication;
  • do not expose webhook secrets in frontend or mobile code;
  • return 2xx only when the event has been successfully received.

Example webhook handler flow

flowchart TD A[Receive POST request] --> B[Read raw request body] B --> C[Verify X-MeSomb-Webhook-Signature] C --> D[Parse JSON event] D --> E[Check event.id for duplicates] E --> F[Process event by type] F --> G[Store processing result] G --> H[Return 200 or 204]

Webhook endpoints should respond quickly.

For production systems, avoid running heavy business logic directly inside the webhook HTTP request.

Recommended approach:

  1. Verify the signature.
  2. Store the event.
  3. Return a 2xx response.
  4. Process the event asynchronously using a background worker.

This reduces timeout risks and improves webhook delivery reliability.