curl --request POST \
--url https://api.synci.io/managed/v1/webhooks \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"events": []
}
'const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', events: []})
};
fetch('https://api.synci.io/managed/v1/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.synci.io/managed/v1/webhooks"
payload = {
"url": "<string>",
"events": []
}
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.synci.io/managed/v1/webhooks",
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([
'url' => '<string>',
'events' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json"
],
]);
$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://api.synci.io/managed/v1/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Basic <encoded-value>")
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))
}{}{
"message": "<string>",
"errors": {}
}Register a webhook endpoint
The endpoint’s signing secret is included in this response only; it
cannot be read again later, but can be rotated at any time. An app may
hold a small fixed number of endpoints (403 when exceeded), and an
approved app needs a Synci plan first (402).
curl --request POST \
--url https://api.synci.io/managed/v1/webhooks \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"events": []
}
'const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', events: []})
};
fetch('https://api.synci.io/managed/v1/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.synci.io/managed/v1/webhooks"
payload = {
"url": "<string>",
"events": []
}
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.synci.io/managed/v1/webhooks",
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([
'url' => '<string>',
'events' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json"
],
]);
$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://api.synci.io/managed/v1/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Basic <encoded-value>")
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))
}{}{
"message": "<string>",
"errors": {}
}Authorizations
Username = your client id. Password = your client secret.
So the base64-encoded username:password described below is
client_id:client_secret:
Authorization: Basic base64(YOUR_CLIENT_ID:YOUR_CLIENT_SECRET)
Most HTTP clients build that header for you:
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
https://api.synci.io/managed/v1/users
Both values come from Developers → Apps → your app. The
secret is shown once at creation and is prefixed oac_.
Body
The HTTPS URL that will receive event deliveries for every user your app manages.
512The event types this endpoint should receive: the bank-data events
(transactions.created, transactions.updated, balance.updated,
holdings.updated, account.*), the connection lifecycle
(connection.*) and portal.user.verified. Legacy bank_account.*
aliases are not available on this surface.
1transactions.created, transactions.updated, balance.updated, holdings.updated, account.created, account.updated, account.deleted, connection.created, connection.activated, connection.reauthorized, connection.expiring, connection.expired, connection.failing, connection.recovered, connection.disabled, connection.deleted, portal.user.verified Optional label to help you identify the endpoint.
255Whether the endpoint receives deliveries. Defaults to true.
When true, sensitive account identifiers (IBAN/BBAN) are omitted
from delivered payloads. They are omitted regardless unless your
app has been approved for the sensitive:read scope.
Not available on app-level endpoints: an app receives events for every user it manages, so a per-account filter has no meaning here.
Not available on app-level endpoints: deliveries always use the current (v2) payload shape.
Response
The response is of type object.