curl --request POST \
--url https://api.pay.aptahq.com/v1/webhooks/{provider}const options = {method: 'POST'};
fetch('https://api.pay.aptahq.com/v1/webhooks/{provider}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/webhooks/{provider}"
response = requests.post(url)
print(response.text)Provider ingress (NOT for tenants)
Where the PROVIDER tells the gateway a payment’s outcome changed. Documented for completeness — a tenant never calls this. You do not implement it, you do not send to it; the provider does, and the gateway turns what arrives into the canonical webhook you receive at YOUR callback URL, signed by us. See docs/TENANT_INTEGRATION.md for the one you actually handle.
Listed here so the surface is honest about what exists and how it is protected. One path per provider, because sniffing the body to guess the sender is the ambiguity to avoid when two providers are live at once.
Gated by the PROVIDER’s own signature over the raw bytes, not by tenant auth. Exempt from rate limiting (a provider retrying into a 429 turns one notification into hours of retries) but never from the signature check, and capped at 64 KB.
You receive the canonical version of these events at YOUR callback URL, signed by us — see docs/TENANT_INTEGRATION.md.
curl --request POST \
--url https://api.pay.aptahq.com/v1/webhooks/{provider}const options = {method: 'POST'};
fetch('https://api.pay.aptahq.com/v1/webhooks/{provider}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/webhooks/{provider}"
response = requests.post(url)
print(response.text)Path Parameters
eversend, flutterwave, stripe Response
Accepted, ignored as a replay, or unmatched. A 200 here means "received", not "applied".