curl --request POST \
--url https://app.sideshift.app/api/embed/webhooks/test \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"eventType": "withdrawal.updated",
"status": "in_transit",
"amountCents": 25000,
"feeCents": 250
}
'import requests
url = "https://app.sideshift.app/api/embed/webhooks/test"
payload = {
"eventType": "withdrawal.updated",
"status": "in_transit",
"amountCents": 25000,
"feeCents": 250
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
eventType: 'withdrawal.updated',
status: 'in_transit',
amountCents: 25000,
feeCents: 250
})
};
fetch('https://app.sideshift.app/api/embed/webhooks/test', 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://app.sideshift.app/api/embed/webhooks/test",
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([
'eventType' => 'withdrawal.updated',
'status' => 'in_transit',
'amountCents' => 25000,
'feeCents' => 250
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$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://app.sideshift.app/api/embed/webhooks/test"
payload := strings.NewReader("{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<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://app.sideshift.app/api/embed/webhooks/test")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/embed/webhooks/test")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"eventType": "withdrawal.updated",
"delivered": true,
"sandbox": true,
"paymentId": "pay_test_5f4c1a2e",
"sideshiftAccountId": "acct_a1b2c3d4e5f6",
"amountCents": 25000,
"feeCents": 250,
"netAmountCents": 24750,
"status": "in_transit"
}
}{
"success": false,
"error": {
"code": "WEBHOOK_DELIVERY_FAILED",
"message": "No webhook URL configured"
}
}Deliver one synthetic event to your sandbox webhook endpoint, signed with your sandbox secret and
recorded in GET /webhook-logs exactly like a real delivery. Use it to exercise every handler before
going live. Live keys receive 403.
Every event type you can subscribe to is supported, and the event is delivered whether or not your
sandbox endpoint is subscribed to it, so a handler can be tested before the subscription is switched on.
The payload has the same shape as the real event; metadata.test is "true" and metadata.sandbox is
"true" so a receiver can tell a rehearsal apart. Fields that do not apply to the chosen event are ignored.
curl --request POST \
--url https://app.sideshift.app/api/embed/webhooks/test \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"eventType": "withdrawal.updated",
"status": "in_transit",
"amountCents": 25000,
"feeCents": 250
}
'import requests
url = "https://app.sideshift.app/api/embed/webhooks/test"
payload = {
"eventType": "withdrawal.updated",
"status": "in_transit",
"amountCents": 25000,
"feeCents": 250
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
eventType: 'withdrawal.updated',
status: 'in_transit',
amountCents: 25000,
feeCents: 250
})
};
fetch('https://app.sideshift.app/api/embed/webhooks/test', 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://app.sideshift.app/api/embed/webhooks/test",
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([
'eventType' => 'withdrawal.updated',
'status' => 'in_transit',
'amountCents' => 25000,
'feeCents' => 250
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$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://app.sideshift.app/api/embed/webhooks/test"
payload := strings.NewReader("{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<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://app.sideshift.app/api/embed/webhooks/test")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/embed/webhooks/test")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"eventType\": \"withdrawal.updated\",\n \"status\": \"in_transit\",\n \"amountCents\": 25000,\n \"feeCents\": 250\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"eventType": "withdrawal.updated",
"delivered": true,
"sandbox": true,
"paymentId": "pay_test_5f4c1a2e",
"sideshiftAccountId": "acct_a1b2c3d4e5f6",
"amountCents": 25000,
"feeCents": 250,
"netAmountCents": 24750,
"status": "in_transit"
}
}{
"success": false,
"error": {
"code": "WEBHOOK_DELIVERY_FAILED",
"message": "No webhook URL configured"
}
}Authorizations
Your SideShift Connect API key (sk_live_* or sk_test_*). Generate from Settings → Connect.
Body
deposit.pending, deposit.confirmed, deposit.failed, transfer.completed, withdrawal.created, withdrawal.updated, withdrawal.completed, withdrawal.failed, account.risk_flagged Account id to place in the payload. Defaults to your company id.
x >= 1x >= 0Defaults to amountCents - feeCents.
x >= 1deposit.* events only. Minted when omitted.
The payment, transfer or withdrawal id to echo. Minted when omitted.
withdrawal.updated only. Defaults to in_transit.
requested, awaiting_payment, in_transit, completed, failed, canceled, denied Show child attributes
Show child attributes