Webhooks
Stripe Webhook
Receive and process webhook events from Stripe.
POST
/
webhooks
/
stripe
Stripe webhook receiver
curl --request POST \
--url https://billing.example.com/webhooks/stripe \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--header 'Stripe-Signature: <stripe-signature>' \
--data '{}'import requests
url = "https://billing.example.com/webhooks/stripe"
payload = {}
headers = {
"Stripe-Signature": "<stripe-signature>",
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Stripe-Signature': '<stripe-signature>',
Authorization: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
};
fetch('https://billing.example.com/webhooks/stripe', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://billing.example.com/webhooks/stripe",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json",
"Stripe-Signature: <stripe-signature>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://billing.example.com/webhooks/stripe"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Stripe-Signature", "<stripe-signature>")
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://billing.example.com/webhooks/stripe")
.header("Stripe-Signature", "<stripe-signature>")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/webhooks/stripe")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Stripe-Signature"] = '<stripe-signature>'
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"reason": "<string>"
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}This endpoint receives webhook events from Stripe when payment-related events
occur, such as successful charges, failed payments, and subscription updates.
This endpoint verifies the webhook signature using your Stripe webhook secret.
Configure this URL in your Stripe Dashboard under Developers > Webhooks with
the URL
https://api.recurso.dev/webhooks/stripe.Example Request
Stripe sends a POST request with event data:curl -X POST https://api.recurso.dev/webhooks/stripe \
-H "Content-Type: application/json" \
-H "Stripe-Signature: t=1687000000,v1=stripe_hmac_signature_here" \
-d '{
"id": "evt_StripeABC123",
"object": "event",
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_StripeDEF456",
"amount": 5899,
"currency": "usd",
"status": "succeeded"
}
}
}'
Response
Returns200 OK on successful processing.
{
"status": "ok"
}
If signature verification fails, the endpoint returns
400 Bad Request and the
event is not processed. Ensure your Stripe webhook secret in Recurso matches
the one configured in the Stripe Dashboard.Authorizations
Headers
Stripe webhook signature header.
Body
application/json
Raw Stripe event payload.
⌘I
Stripe webhook receiver
curl --request POST \
--url https://billing.example.com/webhooks/stripe \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--header 'Stripe-Signature: <stripe-signature>' \
--data '{}'import requests
url = "https://billing.example.com/webhooks/stripe"
payload = {}
headers = {
"Stripe-Signature": "<stripe-signature>",
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Stripe-Signature': '<stripe-signature>',
Authorization: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
};
fetch('https://billing.example.com/webhooks/stripe', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://billing.example.com/webhooks/stripe",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json",
"Stripe-Signature: <stripe-signature>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://billing.example.com/webhooks/stripe"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Stripe-Signature", "<stripe-signature>")
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://billing.example.com/webhooks/stripe")
.header("Stripe-Signature", "<stripe-signature>")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/webhooks/stripe")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Stripe-Signature"] = '<stripe-signature>'
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"reason": "<string>"
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}