cURL
curl --request POST \
--url https://api.finosu.com/webhooks/customers/upsert \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"customerId": "customer-12345",
"personalData": {
"name": "John Doe",
"email": "[email protected]",
"birthday": "1985-06-15",
"firstName": "John",
"lastName": "Doe",
"phone": "+14155551234",
"streetAddress1": "123 Main Street",
"streetAddress2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102",
"socialSecurityNumberLastFour": "1234",
"countryCode": "US",
"timezoneName": "America/Los_Angeles",
"preferredLanguage": "ENGLISH",
"address": "<string>"
},
"autodialerConsent": true,
"externalMetadata": {
"home_phone": "+14155555555",
"cell_phone": "+14155556666",
"employer_name": "Example employer",
"employer_address": "456 Business Ave",
"employer_city": "San Francisco",
"employer_state": "CA",
"employer_zip": "94103",
"employer_department": "Sales",
"employer_phone": "+14155557777",
"employer_direct_line": "+14155558888",
"pay_frequency": "biweekly",
"pay_day": "Monday"
}
}
'import requests
url = "https://api.finosu.com/webhooks/customers/upsert"
payload = {
"customerId": "customer-12345",
"personalData": {
"name": "John Doe",
"email": "[email protected]",
"birthday": "1985-06-15",
"firstName": "John",
"lastName": "Doe",
"phone": "+14155551234",
"streetAddress1": "123 Main Street",
"streetAddress2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102",
"socialSecurityNumberLastFour": "1234",
"countryCode": "US",
"timezoneName": "America/Los_Angeles",
"preferredLanguage": "ENGLISH",
"address": "<string>"
},
"autodialerConsent": True,
"externalMetadata": {
"home_phone": "+14155555555",
"cell_phone": "+14155556666",
"employer_name": "Example employer",
"employer_address": "456 Business Ave",
"employer_city": "San Francisco",
"employer_state": "CA",
"employer_zip": "94103",
"employer_department": "Sales",
"employer_phone": "+14155557777",
"employer_direct_line": "+14155558888",
"pay_frequency": "biweekly",
"pay_day": "Monday"
}
}
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({
customerId: 'customer-12345',
personalData: {
name: 'John Doe',
email: '[email protected]',
birthday: '1985-06-15',
firstName: 'John',
lastName: 'Doe',
phone: '+14155551234',
streetAddress1: '123 Main Street',
streetAddress2: 'Apt 4B',
city: 'San Francisco',
state: 'CA',
zipCode: '94102',
socialSecurityNumberLastFour: '1234',
countryCode: 'US',
timezoneName: 'America/Los_Angeles',
preferredLanguage: 'ENGLISH',
address: '<string>'
},
autodialerConsent: true,
externalMetadata: {
home_phone: '+14155555555',
cell_phone: '+14155556666',
employer_name: 'Example employer',
employer_address: '456 Business Ave',
employer_city: 'San Francisco',
employer_state: 'CA',
employer_zip: '94103',
employer_department: 'Sales',
employer_phone: '+14155557777',
employer_direct_line: '+14155558888',
pay_frequency: 'biweekly',
pay_day: 'Monday'
}
})
};
fetch('https://api.finosu.com/webhooks/customers/upsert', 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://api.finosu.com/webhooks/customers/upsert",
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([
'customerId' => 'customer-12345',
'personalData' => [
'name' => 'John Doe',
'email' => '[email protected]',
'birthday' => '1985-06-15',
'firstName' => 'John',
'lastName' => 'Doe',
'phone' => '+14155551234',
'streetAddress1' => '123 Main Street',
'streetAddress2' => 'Apt 4B',
'city' => 'San Francisco',
'state' => 'CA',
'zipCode' => '94102',
'socialSecurityNumberLastFour' => '1234',
'countryCode' => 'US',
'timezoneName' => 'America/Los_Angeles',
'preferredLanguage' => 'ENGLISH',
'address' => '<string>'
],
'autodialerConsent' => true,
'externalMetadata' => [
'home_phone' => '+14155555555',
'cell_phone' => '+14155556666',
'employer_name' => 'Example employer',
'employer_address' => '456 Business Ave',
'employer_city' => 'San Francisco',
'employer_state' => 'CA',
'employer_zip' => '94103',
'employer_department' => 'Sales',
'employer_phone' => '+14155557777',
'employer_direct_line' => '+14155558888',
'pay_frequency' => 'biweekly',
'pay_day' => 'Monday'
]
]),
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://api.finosu.com/webhooks/customers/upsert"
payload := strings.NewReader("{\n \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\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://api.finosu.com/webhooks/customers/upsert")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.finosu.com/webhooks/customers/upsert")
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 \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"customer_id": "customer-12345",
"created": "2025-10-31T18:30:00Z",
"updated": "2025-10-31T18:30:00Z"
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "Internal server error processing customer webhook"
}Customers
Upsert a Customer (Webhook)
Your system posts customer data to Finosu. This is an inbound API endpoint, not an outbound callback.
POST
/
webhooks
/
customers
/
upsert
cURL
curl --request POST \
--url https://api.finosu.com/webhooks/customers/upsert \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"customerId": "customer-12345",
"personalData": {
"name": "John Doe",
"email": "[email protected]",
"birthday": "1985-06-15",
"firstName": "John",
"lastName": "Doe",
"phone": "+14155551234",
"streetAddress1": "123 Main Street",
"streetAddress2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102",
"socialSecurityNumberLastFour": "1234",
"countryCode": "US",
"timezoneName": "America/Los_Angeles",
"preferredLanguage": "ENGLISH",
"address": "<string>"
},
"autodialerConsent": true,
"externalMetadata": {
"home_phone": "+14155555555",
"cell_phone": "+14155556666",
"employer_name": "Example employer",
"employer_address": "456 Business Ave",
"employer_city": "San Francisco",
"employer_state": "CA",
"employer_zip": "94103",
"employer_department": "Sales",
"employer_phone": "+14155557777",
"employer_direct_line": "+14155558888",
"pay_frequency": "biweekly",
"pay_day": "Monday"
}
}
'import requests
url = "https://api.finosu.com/webhooks/customers/upsert"
payload = {
"customerId": "customer-12345",
"personalData": {
"name": "John Doe",
"email": "[email protected]",
"birthday": "1985-06-15",
"firstName": "John",
"lastName": "Doe",
"phone": "+14155551234",
"streetAddress1": "123 Main Street",
"streetAddress2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102",
"socialSecurityNumberLastFour": "1234",
"countryCode": "US",
"timezoneName": "America/Los_Angeles",
"preferredLanguage": "ENGLISH",
"address": "<string>"
},
"autodialerConsent": True,
"externalMetadata": {
"home_phone": "+14155555555",
"cell_phone": "+14155556666",
"employer_name": "Example employer",
"employer_address": "456 Business Ave",
"employer_city": "San Francisco",
"employer_state": "CA",
"employer_zip": "94103",
"employer_department": "Sales",
"employer_phone": "+14155557777",
"employer_direct_line": "+14155558888",
"pay_frequency": "biweekly",
"pay_day": "Monday"
}
}
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({
customerId: 'customer-12345',
personalData: {
name: 'John Doe',
email: '[email protected]',
birthday: '1985-06-15',
firstName: 'John',
lastName: 'Doe',
phone: '+14155551234',
streetAddress1: '123 Main Street',
streetAddress2: 'Apt 4B',
city: 'San Francisco',
state: 'CA',
zipCode: '94102',
socialSecurityNumberLastFour: '1234',
countryCode: 'US',
timezoneName: 'America/Los_Angeles',
preferredLanguage: 'ENGLISH',
address: '<string>'
},
autodialerConsent: true,
externalMetadata: {
home_phone: '+14155555555',
cell_phone: '+14155556666',
employer_name: 'Example employer',
employer_address: '456 Business Ave',
employer_city: 'San Francisco',
employer_state: 'CA',
employer_zip: '94103',
employer_department: 'Sales',
employer_phone: '+14155557777',
employer_direct_line: '+14155558888',
pay_frequency: 'biweekly',
pay_day: 'Monday'
}
})
};
fetch('https://api.finosu.com/webhooks/customers/upsert', 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://api.finosu.com/webhooks/customers/upsert",
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([
'customerId' => 'customer-12345',
'personalData' => [
'name' => 'John Doe',
'email' => '[email protected]',
'birthday' => '1985-06-15',
'firstName' => 'John',
'lastName' => 'Doe',
'phone' => '+14155551234',
'streetAddress1' => '123 Main Street',
'streetAddress2' => 'Apt 4B',
'city' => 'San Francisco',
'state' => 'CA',
'zipCode' => '94102',
'socialSecurityNumberLastFour' => '1234',
'countryCode' => 'US',
'timezoneName' => 'America/Los_Angeles',
'preferredLanguage' => 'ENGLISH',
'address' => '<string>'
],
'autodialerConsent' => true,
'externalMetadata' => [
'home_phone' => '+14155555555',
'cell_phone' => '+14155556666',
'employer_name' => 'Example employer',
'employer_address' => '456 Business Ave',
'employer_city' => 'San Francisco',
'employer_state' => 'CA',
'employer_zip' => '94103',
'employer_department' => 'Sales',
'employer_phone' => '+14155557777',
'employer_direct_line' => '+14155558888',
'pay_frequency' => 'biweekly',
'pay_day' => 'Monday'
]
]),
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://api.finosu.com/webhooks/customers/upsert"
payload := strings.NewReader("{\n \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\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://api.finosu.com/webhooks/customers/upsert")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.finosu.com/webhooks/customers/upsert")
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 \"customerId\": \"customer-12345\",\n \"personalData\": {\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"birthday\": \"1985-06-15\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"phone\": \"+14155551234\",\n \"streetAddress1\": \"123 Main Street\",\n \"streetAddress2\": \"Apt 4B\",\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"zipCode\": \"94102\",\n \"socialSecurityNumberLastFour\": \"1234\",\n \"countryCode\": \"US\",\n \"timezoneName\": \"America/Los_Angeles\",\n \"preferredLanguage\": \"ENGLISH\",\n \"address\": \"<string>\"\n },\n \"autodialerConsent\": true,\n \"externalMetadata\": {\n \"home_phone\": \"+14155555555\",\n \"cell_phone\": \"+14155556666\",\n \"employer_name\": \"Example employer\",\n \"employer_address\": \"456 Business Ave\",\n \"employer_city\": \"San Francisco\",\n \"employer_state\": \"CA\",\n \"employer_zip\": \"94103\",\n \"employer_department\": \"Sales\",\n \"employer_phone\": \"+14155557777\",\n \"employer_direct_line\": \"+14155558888\",\n \"pay_frequency\": \"biweekly\",\n \"pay_day\": \"Monday\"\n }\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"customer_id": "customer-12345",
"created": "2025-10-31T18:30:00Z",
"updated": "2025-10-31T18:30:00Z"
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "Internal server error processing customer webhook"
}This is an inbound API request: your system posts customer data to Finosu with
Provide
X-API-Key. It is separate from outbound call-result webhooks.
Use camelCase for new integrations. Existing snake_case request fields remain
accepted, including fields inside personalData. Both spellings can be mixed.
If both spellings of a field are supplied, the camelCase value takes precedence;
when both personalData and personal_data are present, personalData is selected
as a whole object rather than merged. Send each field only once.
Keys inside externalMetadata are caller-defined and are preserved without renaming.
For example:
{
"customerId": "CUST-12345",
"personalData": {
"email": "[email protected]",
"birthday": "1985-06-15",
"firstName": "Alex",
"lastName": "Example",
"phone": "+14155551234",
"streetAddress1": "123 Main Street",
"zipCode": "94102"
},
"autodialerConsent": true,
"externalMetadata": {}
}
name or both firstName and lastName inside personalData.
Missing required fields or name data returns 422. The response identifier
remains customer_id; updated may be null.
Validation Errors
Invalid phone or birthday input, including an empty or whitespace-only birthday, returns HTTP422 Unprocessable Content with a string
detail. Request-schema errors also return 422, with an array of field errors. Unexpected
server failures remain 500; a server response failure is not a request-validation error.
Supplied personalData.timezoneName values must be valid IANA timezones; invalid
values return 422 before persistence. Omitted or null timezones retain their existing behavior.Body
application/json
Customer data to upsert
Use camelCase request fields. Legacy snake_case names remain accepted at both payload levels. CamelCase takes precedence when both spellings are supplied; duplicate personalData objects are selected, not merged. Keys inside externalMetadata are preserved as supplied.