curl --request PUT \
--url https://api.monaco.com/v1/contacts/ \
--header 'Content-Type: application/json' \
--data '
{
"email": "jane@acme.com",
"linkedin_url": "https://linkedin.com/in/janesmith",
"first_name": "Jane",
"last_name": "Smith",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"location": "San Francisco, CA",
"account_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "acme.com",
"do_not_contact": false,
"tags": [
"550e8400-e29b-41d4-a716-446655440001"
],
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
}
'import requests
url = "https://api.monaco.com/v1/contacts/"
payload = {
"email": "jane@acme.com",
"linkedin_url": "https://linkedin.com/in/janesmith",
"first_name": "Jane",
"last_name": "Smith",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"location": "San Francisco, CA",
"account_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "acme.com",
"do_not_contact": False,
"tags": ["550e8400-e29b-41d4-a716-446655440001"],
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
}
headers = {"Content-Type": "application/json"}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'jane@acme.com',
linkedin_url: 'https://linkedin.com/in/janesmith',
first_name: 'Jane',
last_name: 'Smith',
title: 'VP of Engineering',
phone_number: '+1-415-555-0132',
location: 'San Francisco, CA',
account_id: '550e8400-e29b-41d4-a716-446655440000',
domain: 'acme.com',
do_not_contact: false,
tags: ['550e8400-e29b-41d4-a716-446655440001'],
'custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d': 'economic_buyer'
})
};
fetch('https://api.monaco.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.monaco.com/v1/contacts/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'jane@acme.com',
'linkedin_url' => 'https://linkedin.com/in/janesmith',
'first_name' => 'Jane',
'last_name' => 'Smith',
'title' => 'VP of Engineering',
'phone_number' => '+1-415-555-0132',
'location' => 'San Francisco, CA',
'account_id' => '550e8400-e29b-41d4-a716-446655440000',
'domain' => 'acme.com',
'do_not_contact' => false,
'tags' => [
'550e8400-e29b-41d4-a716-446655440001'
],
'custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d' => 'economic_buyer'
]),
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.monaco.com/v1/contacts/"
payload := strings.NewReader("{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.monaco.com/v1/contacts/")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.monaco.com/v1/contacts/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "con_abc123",
"account_id": "acc_def456",
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@acme.com",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"linkedin_url": "https://linkedin.com/in/janesmith",
"location": "San Francisco, CA",
"source": "api",
"do_not_contact": false,
"notes": "Met at SaaStr 2025",
"scoring": {
"heat_score": "Hot"
},
"tags": [
"Decision Maker"
],
"created_at": "2025-06-15T10:30:00Z",
"updated_at": "2026-04-21T12:00:00Z",
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
},
"meta": {
"timestamp": "2026-04-21T12:00:00Z"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}Upsert a Contact
Creates a new contact or updates an existing one.
Identifiers — with only linkedin_url, also pass account_id or domain.
Duplicate resolution — matched against existing contacts by email (case-insensitive), then linkedin_url. A match is updated in place, otherwise a contact is created. Unlike POST /contacts, a duplicate identifier is not a 409. The exception: if the identifiers resolve to two different contacts on the same account, neither can be updated and a 409 is returned.
Account resolution priority — when creating: account_id, then domain, then the domain parsed from email.
Enrichment — creating a contact synchronously enriches it and resolves or creates its account, so those requests can take several seconds. Use generous timeouts (10s+) and keep upserts off hot paths.
curl --request PUT \
--url https://api.monaco.com/v1/contacts/ \
--header 'Content-Type: application/json' \
--data '
{
"email": "jane@acme.com",
"linkedin_url": "https://linkedin.com/in/janesmith",
"first_name": "Jane",
"last_name": "Smith",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"location": "San Francisco, CA",
"account_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "acme.com",
"do_not_contact": false,
"tags": [
"550e8400-e29b-41d4-a716-446655440001"
],
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
}
'import requests
url = "https://api.monaco.com/v1/contacts/"
payload = {
"email": "jane@acme.com",
"linkedin_url": "https://linkedin.com/in/janesmith",
"first_name": "Jane",
"last_name": "Smith",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"location": "San Francisco, CA",
"account_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "acme.com",
"do_not_contact": False,
"tags": ["550e8400-e29b-41d4-a716-446655440001"],
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
}
headers = {"Content-Type": "application/json"}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'jane@acme.com',
linkedin_url: 'https://linkedin.com/in/janesmith',
first_name: 'Jane',
last_name: 'Smith',
title: 'VP of Engineering',
phone_number: '+1-415-555-0132',
location: 'San Francisco, CA',
account_id: '550e8400-e29b-41d4-a716-446655440000',
domain: 'acme.com',
do_not_contact: false,
tags: ['550e8400-e29b-41d4-a716-446655440001'],
'custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d': 'economic_buyer'
})
};
fetch('https://api.monaco.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.monaco.com/v1/contacts/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'jane@acme.com',
'linkedin_url' => 'https://linkedin.com/in/janesmith',
'first_name' => 'Jane',
'last_name' => 'Smith',
'title' => 'VP of Engineering',
'phone_number' => '+1-415-555-0132',
'location' => 'San Francisco, CA',
'account_id' => '550e8400-e29b-41d4-a716-446655440000',
'domain' => 'acme.com',
'do_not_contact' => false,
'tags' => [
'550e8400-e29b-41d4-a716-446655440001'
],
'custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d' => 'economic_buyer'
]),
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.monaco.com/v1/contacts/"
payload := strings.NewReader("{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.monaco.com/v1/contacts/")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.monaco.com/v1/contacts/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"jane@acme.com\",\n \"linkedin_url\": \"https://linkedin.com/in/janesmith\",\n \"first_name\": \"Jane\",\n \"last_name\": \"Smith\",\n \"title\": \"VP of Engineering\",\n \"phone_number\": \"+1-415-555-0132\",\n \"location\": \"San Francisco, CA\",\n \"account_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"domain\": \"acme.com\",\n \"do_not_contact\": false,\n \"tags\": [\n \"550e8400-e29b-41d4-a716-446655440001\"\n ],\n \"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\": \"economic_buyer\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "con_abc123",
"account_id": "acc_def456",
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@acme.com",
"title": "VP of Engineering",
"phone_number": "+1-415-555-0132",
"linkedin_url": "https://linkedin.com/in/janesmith",
"location": "San Francisco, CA",
"source": "api",
"do_not_contact": false,
"notes": "Met at SaaStr 2025",
"scoring": {
"heat_score": "Hot"
},
"tags": [
"Decision Maker"
],
"created_at": "2025-06-15T10:30:00Z",
"updated_at": "2026-04-21T12:00:00Z",
"custom_field_1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "economic_buyer"
},
"meta": {
"timestamp": "2026-04-21T12:00:00Z"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}Body
Request body for creating a contact via POST or upserting via PUT.
Custom fields can be passed as additional keys prefixed with custom_field_.
Whether the contact is an inbound lead. When true and this request creates a new contact, Monaco runs inbound-lead qualification on it. Ignored when the request matches an existing contact.
Email address of the contact. Either email or linkedin_url is required.
"jane@acme.com"
LinkedIn profile URL (a linkedin.com/in/... URL). Either email or linkedin_url is required.
"https://linkedin.com/in/janesmith"
First name of the contact
"Jane"
Last name of the contact
"Smith"
Job title of the contact
"VP of Engineering"
Phone number of the contact
"+1-415-555-0132"
Location of the contact
"San Francisco, CA"
ID of the account to associate the contact with
Domain of the contact's company (used for account resolution)
"acme.com"
Whether the contact has opted out of outreach
Notes about the contact
"Met at conference in 2025"
Tag IDs to associate with the contact. Appended to the contact's existing tags.