Stripe webhook — idempotent, settled-only crediting (PUBLIC).
const url = 'https://api.tradr.cloud/api/billing/webhook';const options = {method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.tradr.cloud/api/billing/webhook \ --header 'Content-Type: application/json' \ --data '{}'PUBLIC endpoint (NO session auth — Stripe is the caller) and IP-rate limited. Reads the UNMODIFIED RAW request body and verifies the Stripe-Signature header against STRIPE_WEBHOOK_SECRET over the exact raw bytes (REQ-3.1) — an invalid or missing signature returns 400 and no wallet is touched. The verified event is dispatched to the idempotent settled-only handler; its outcome maps to 200 (credited / acked / duplicate / refused / reversed — terminal, Stripe stops retrying) or a retryable 5xx (transient verify-failure, no row written — Stripe redelivers). NOTE: this route MUST receive the raw body before any JSON parse; a global JSON body parser would silently break signatures.
Request Bodyrequired
Section titled “Request Bodyrequired”Raw Stripe event JSON (verified by signature, not parsed by the framework).
object
Examplegenerated
{}Responses
Section titled “Responses”Event acknowledged (credited / acked / duplicate / refused / reversed).
Missing/invalid signature or Stripe unconfigured — no wallet touched.
Transient verify-failure — Stripe should redeliver.