Create Contact
curl --request POST \
--url https://api.example.com/v1/contacts \
--header 'Content-Type: application/json' \
--data '
{
"full_name": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"email": "<string>",
"phone": "<string>",
"job_title": "<string>",
"company": "<string>",
"related_company_id": "<string>",
"linkedin_url": "<string>",
"priority": {},
"tags": [
{}
],
"custom_fields": {},
"created_date": "<string>"
}
'import requests
url = "https://api.example.com/v1/contacts"
payload = {
"full_name": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"email": "<string>",
"phone": "<string>",
"job_title": "<string>",
"company": "<string>",
"related_company_id": "<string>",
"linkedin_url": "<string>",
"priority": {},
"tags": [{}],
"custom_fields": {},
"created_date": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
full_name: '<string>',
first_name: '<string>',
last_name: '<string>',
email: '<string>',
phone: '<string>',
job_title: '<string>',
company: '<string>',
related_company_id: '<string>',
linkedin_url: '<string>',
priority: {},
tags: [{}],
custom_fields: {},
created_date: '<string>'
})
};
fetch('https://api.example.com/v1/contacts', 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.example.com/v1/contacts",
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([
'full_name' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'email' => '<string>',
'phone' => '<string>',
'job_title' => '<string>',
'company' => '<string>',
'related_company_id' => '<string>',
'linkedin_url' => '<string>',
'priority' => [
],
'tags' => [
[
]
],
'custom_fields' => [
],
'created_date' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"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.example.com/v1/contacts"
payload := strings.NewReader("{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/v1/contacts")
.header("Content-Type", "application/json")
.body("{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/contacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"email": "<string>",
"priority": 123,
"created_date": "<string>"
}
}Contacts
Create Contact
Add a new contact to your workspace
POST
/
v1
/
contacts
Create Contact
curl --request POST \
--url https://api.example.com/v1/contacts \
--header 'Content-Type: application/json' \
--data '
{
"full_name": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"email": "<string>",
"phone": "<string>",
"job_title": "<string>",
"company": "<string>",
"related_company_id": "<string>",
"linkedin_url": "<string>",
"priority": {},
"tags": [
{}
],
"custom_fields": {},
"created_date": "<string>"
}
'import requests
url = "https://api.example.com/v1/contacts"
payload = {
"full_name": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"email": "<string>",
"phone": "<string>",
"job_title": "<string>",
"company": "<string>",
"related_company_id": "<string>",
"linkedin_url": "<string>",
"priority": {},
"tags": [{}],
"custom_fields": {},
"created_date": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
full_name: '<string>',
first_name: '<string>',
last_name: '<string>',
email: '<string>',
phone: '<string>',
job_title: '<string>',
company: '<string>',
related_company_id: '<string>',
linkedin_url: '<string>',
priority: {},
tags: [{}],
custom_fields: {},
created_date: '<string>'
})
};
fetch('https://api.example.com/v1/contacts', 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.example.com/v1/contacts",
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([
'full_name' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'email' => '<string>',
'phone' => '<string>',
'job_title' => '<string>',
'company' => '<string>',
'related_company_id' => '<string>',
'linkedin_url' => '<string>',
'priority' => [
],
'tags' => [
[
]
],
'custom_fields' => [
],
'created_date' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"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.example.com/v1/contacts"
payload := strings.NewReader("{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/v1/contacts")
.header("Content-Type", "application/json")
.body("{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/contacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"full_name\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"email\": \"<string>\",\n \"phone\": \"<string>\",\n \"job_title\": \"<string>\",\n \"company\": \"<string>\",\n \"related_company_id\": \"<string>\",\n \"linkedin_url\": \"<string>\",\n \"priority\": {},\n \"tags\": [\n {}\n ],\n \"custom_fields\": {},\n \"created_date\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"email": "<string>",
"priority": 123,
"created_date": "<string>"
}
}Request
Headers
Authorization: Bearer wbk_your_api_key_here
Content-Type: application/json
Body Parameters
Name handling: Send any of
full_name, first_name + last_name, or just an email. The API splits / composes / derives the missing pieces. It also understands the "Last, First" format.string
Contact’s full name. If only this is given, the API splits on the last whitespace (e.g.
"Hans Müller" → first=Hans, last=Müller). Accepts the "Last, First" format (e.g. "Müller, Hans").string
Contact’s first name. Composed into
full_name if full_name isn’t provided.string
Contact’s last name.
string
Email address. Used for duplicate detection and, as a last resort, to derive a name (e.g.
hans.mueller@x.de → first=Hans, last=Mueller) when no name is given.string
Phone number with country code
string
Job title or position
string
Company or organization name
string
UUID of an existing Company to link this contact to. Also accepts the legacy
company_id key.string
LinkedIn profile URL
string | number
Either
"high" / "medium" / "low" or an integer (1/2/3).array
Array of tag strings for categorization
object
Arbitrary JSON object preserved alongside the contact — ideal for domain-specific columns from imported CSVs (e.g. matter numbers, jurisdiction codes).
string
Optional ISO 8601 timestamp. Honored verbatim if it’s within the last 5 years and no more than 24 h in the future; otherwise the server
now() is used. Never null.Response
object
curl -X POST \
https://data.leadlex.com/functions/v1/api-gateway/v1/contacts \
-H "Authorization: Bearer wbk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"full_name": "Müller, Hans",
"email": "hans@roche.com",
"job_title": "IP Partner",
"company": "Roche AG"
}'
import requests
API_KEY = "wbk_your_api_key_here"
BASE_URL = "https://data.leadlex.com/functions/v1/api-gateway"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Any of these shapes works — the API fills in the rest
data = { "full_name": "Müller, Hans", "email": "hans@roche.com" }
# or
# data = { "first_name": "Hans", "last_name": "Müller", "email": "hans@roche.com" }
# or
# data = { "email": "hans.mueller@roche.com" } # name derived from local part
response = requests.post(f"{BASE_URL}/v1/contacts", headers=headers, json=data)
contact = response.json()["data"]
print(contact["first_name"], contact["last_name"], contact["full_name"])
# → Hans Müller Hans Müller
const response = await fetch(
'https://data.leadlex.com/functions/v1/api-gateway/v1/contacts',
{
method: 'POST',
headers: {
'Authorization': 'Bearer wbk_your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
full_name: 'Müller, Hans',
email: 'hans@roche.com',
job_title: 'IP Partner'
})
}
);
const { data } = await response.json();
console.log(`Created contact: ${data.first_name} ${data.last_name}`);
Example Response
{
"data": {
"id": "789e0123-e45b-67c8-a901-234567890abc",
"first_name": "Hans",
"last_name": "Müller",
"full_name": "Hans Müller",
"email": "hans@roche.com",
"priority": null,
"created_date": "2026-04-21T14:30:00.000Z"
}
}
Validation
At least one of
first_name, last_name, full_name, or email must be provided. If none are present the API returns validation_error.Name derivation rules
Applied in order; the first rule that yields a name wins:"Last, First"format — iffull_namecontains a comma and first/last are empty, it’s split into last / first.- Split
full_name— whenfull_nameis given butfirst_name/last_nameare empty, it’s split on the last whitespace. “Jean-Claude van Damme” → first=Jean-Claude van, last=Damme. - Compose
full_name— whenfirst_name/last_nameare given butfull_nameis empty. - Derive from email — local part is split on
._-+into Title Case tokens.
Duplicate Detection
The API checks for duplicates by:- Exact email match (case-insensitive)
- Full-name ILIKE match
force_create: false on the agent tool to suppress).
Errors
| Status | Code | Description |
|---|---|---|
| 400 | validation_error | No name or email provided |
| 401 | invalid_key | Invalid API key |
| 403 | insufficient_permissions | Missing contacts:write permission |
| 429 | rate_limited | Rate limit exceeded |
Example Validation Error
{
"error": {
"code": "validation_error",
"message": "A name (first_name, last_name, or full_name) or email is required"
}
}