curl --request PATCH \
--url https://api.parley.so/v1/contacts/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"firstName": "<string>",
"lastName": "<string>",
"accountId": "<string>",
"emails": [
"[email protected]"
],
"projectIds": {
"add": [
"<string>"
],
"remove": [
"<string>"
]
},
"fields": {}
}
'import requests
url = "https://api.parley.so/v1/contacts/{id}"
payload = {
"firstName": "<string>",
"lastName": "<string>",
"accountId": "<string>",
"emails": ["[email protected]"],
"projectIds": {
"add": ["<string>"],
"remove": ["<string>"]
},
"fields": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
firstName: '<string>',
lastName: '<string>',
accountId: '<string>',
emails: ['[email protected]'],
projectIds: {add: ['<string>'], remove: ['<string>']},
fields: {}
})
};
fetch('https://api.parley.so/v1/contacts/{id}', 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.parley.so/v1/contacts/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'firstName' => '<string>',
'lastName' => '<string>',
'accountId' => '<string>',
'emails' => [
'[email protected]'
],
'projectIds' => [
'add' => [
'<string>'
],
'remove' => [
'<string>'
]
],
'fields' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.parley.so/v1/contacts/{id}"
payload := strings.NewReader("{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.patch("https://api.parley.so/v1/contacts/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parley.so/v1/contacts/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "cmf2x7z3e0002abcd",
"firstName": "Ada",
"lastName": "Lovelace",
"emails": [
"[email protected]"
],
"account": {
"type": "account",
"id": "cmf2x7r1p0000abcd",
"name": "Acme Corp"
},
"projectCount": 1,
"createdAt": "2026-09-12T10:05:00.000Z",
"updatedAt": "2026-09-12T10:05:00.000Z",
"fields": {
"Contact Type": "Beneficiary",
"Country of Birth": "United Kingdom"
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "The request is invalid.",
"details": {
"issues": [
{
"path": "<string>",
"message": "<string>"
}
]
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid credentials."
}
}{
"error": {
"code": "FORBIDDEN",
"message": "You don't have permission to do this."
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Not found."
}
}{
"error": {
"code": "EMAIL_TAKEN",
"message": "This email address already belongs to another contact."
}
}{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "Too many requests."
}
}Update a contact
Update a contact’s name, account, email address, linked projects, or custom field values. Omitted fields are left unchanged.
curl --request PATCH \
--url https://api.parley.so/v1/contacts/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"firstName": "<string>",
"lastName": "<string>",
"accountId": "<string>",
"emails": [
"[email protected]"
],
"projectIds": {
"add": [
"<string>"
],
"remove": [
"<string>"
]
},
"fields": {}
}
'import requests
url = "https://api.parley.so/v1/contacts/{id}"
payload = {
"firstName": "<string>",
"lastName": "<string>",
"accountId": "<string>",
"emails": ["[email protected]"],
"projectIds": {
"add": ["<string>"],
"remove": ["<string>"]
},
"fields": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
firstName: '<string>',
lastName: '<string>',
accountId: '<string>',
emails: ['[email protected]'],
projectIds: {add: ['<string>'], remove: ['<string>']},
fields: {}
})
};
fetch('https://api.parley.so/v1/contacts/{id}', 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.parley.so/v1/contacts/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'firstName' => '<string>',
'lastName' => '<string>',
'accountId' => '<string>',
'emails' => [
'[email protected]'
],
'projectIds' => [
'add' => [
'<string>'
],
'remove' => [
'<string>'
]
],
'fields' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.parley.so/v1/contacts/{id}"
payload := strings.NewReader("{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.patch("https://api.parley.so/v1/contacts/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parley.so/v1/contacts/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"firstName\": \"<string>\",\n \"lastName\": \"<string>\",\n \"accountId\": \"<string>\",\n \"emails\": [\n \"[email protected]\"\n ],\n \"projectIds\": {\n \"add\": [\n \"<string>\"\n ],\n \"remove\": [\n \"<string>\"\n ]\n },\n \"fields\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "cmf2x7z3e0002abcd",
"firstName": "Ada",
"lastName": "Lovelace",
"emails": [
"[email protected]"
],
"account": {
"type": "account",
"id": "cmf2x7r1p0000abcd",
"name": "Acme Corp"
},
"projectCount": 1,
"createdAt": "2026-09-12T10:05:00.000Z",
"updatedAt": "2026-09-12T10:05:00.000Z",
"fields": {
"Contact Type": "Beneficiary",
"Country of Birth": "United Kingdom"
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "The request is invalid.",
"details": {
"issues": [
{
"path": "<string>",
"message": "<string>"
}
]
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid credentials."
}
}{
"error": {
"code": "FORBIDDEN",
"message": "You don't have permission to do this."
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Not found."
}
}{
"error": {
"code": "EMAIL_TAKEN",
"message": "This email address already belongs to another contact."
}
}{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "Too many requests."
}
}Authorizations
A Parley API key.
Path Parameters
The contact ID.
1Body
First name.
1Last name.
1ID of the account the contact belongs to. null removes the contact from its account.
1The contact's email address, as a list that replaces the current one; [] removes it. A contact has at most one address for now, and an address can belong to only one contact.
1Links to projects to add or remove. Links you don't mention are left unchanged. Each project must be one you can edit. If the contact belongs to an account, that account must be linked to each project too; a project with no accounts gets it linked along with the contact.
Show child attributes
Show child attributes
Custom field values to set on the contact, keyed by field name or ID. A value replaces the current one, null clears it, and fields you don't mention are left alone. Each value must match its field's type: a string for text, long_text, email, url, single_select (one of the field's options), and user (the id of an active user in the organization); a number; true or false; an ISO 8601 date-time or YYYY-MM-DD date; a list of strings for collection ([] clears it); or { streetAddress, cityTown, state, country } for address. At most 50 fields.
Show child attributes
Show child attributes
Response
OK
The contact ID.
1First name. Empty for some contacts created from email.
Last name. Empty for some contacts created from email.
Email addresses, lowercased. A contact has at most one address for now.
The account the contact belongs to, or null.
Show child attributes
Show child attributes
How many projects you can see are linked to the contact. List them by filtering projects by contactId. Linking or unlinking a project doesn't change the contact's updatedAt.
0 <= x <= 9007199254740991When the contact was created.
When the contact was last updated, including changes to its email address. Links to projects and field value changes do not change it.
Custom field values, keyed by field name, with a key for every field defined for contacts (null when unset). The value's shape follows the field's type.
Show child attributes
Show child attributes
Was this page helpful?
