Build payments into your product with TPE virtual. Start integrating →
Logo

Receive webhooks

Register an HTTPS endpoint, verify each delivery's signature, and process events once.

Register an endpoint

Your token needs the webhooks:write scope. The address must be public and use HTTPS.

curl -X POST https://api.mytpe.app/api/ext/webhooks \
  -H "Authorization: Bearer $MYTPE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/hooks/mytpe", "events": ["transaction.paid"] }'

The response holds the signing secret. MyTPE shows it only once, so store it on your server. An empty events list subscribes to every event.

Verify the signature

Each delivery has an X-Mytpe-Signature header:

X-Mytpe-Signature: t=1733745296,v1=5257a869e7ec...c12d

v1 is the HMAC-SHA256 of {t}.{raw body}, keyed with your secret.

  1. Read the raw request body before parsing it.
  2. Compute the HMAC.
  3. Compare it to v1 in constant time.
  4. Refuse the delivery if the values differ, or if t is more than 5 minutes old.
[$t, $v1] = sscanf($_SERVER['HTTP_X_MYTPE_SIGNATURE'], 't=%d,v1=%s');
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', "{$t}.".$body, $webhookSecret);

if (! hash_equals($expected, $v1) || abs(time() - $t) > 300) {
    http_response_code(400);
    exit;
}

Respond and process

  1. Answer with a 2xx status within 10 seconds. Do slow work after you answer.
  2. Use the payload's id to skip events you've already processed, because a delivery can arrive more than once.

A non-2xx answer, a redirect or a connection error is retried, up to 5 attempts in all, after 10 seconds, 1 minute, 5 minutes and 15 minutes. MyTPE doesn't follow redirects.

To inspect attempts, call GET /webhooks/{id}/deliveries. To send one again, call POST /webhooks/{id}/deliveries/{did}/redeliver.

Rotate the signing secret

Call POST /webhooks/{id}/regenerate-secret. The old secret stops working immediately, so deploy the new one straight away.

For the payload format, see Webhook events.

On this page