Skip to contentDevelopersPrezly website
Contacts and outreach

Working with contacts

Find CRM contacts, create people or organisations, and update records without replacing data accidentally.

Use CRM contacts to keep track of the people and organisations you work with. A contact is an account record; adding one does not send an email or establish that its email address is subscribed.

CRM contacts under /contacts are different from newsroom press contacts under /newsrooms/{newsroom_id}/contacts. Press contacts are the spokespeople displayed on a newsroom. Creating a CRM contact does not add someone to that public page.

Prepare access and identifiers

Load your credential into PREZLY_API_TOKEN. Personal tokens need contacts:read for retrieval/search and contacts:write for changes. The owner must also have the corresponding contact permissions. Keep contact data and credentials on your server, rather than returning your CRM directory to visitors of a public newsroom.

Contacts use a numeric id. Store that returned ID alongside the source-system ID in a sync integration. Email addresses and display names can change, and a repeated Create request is not an upsert.

Find and inspect an existing contact

Start with a small page:

curl --fail-with-body --silent --show-error --get 'https://api.prezly.com/v2/contacts' \
  --header "Authorization: Bearer $PREZLY_API_TOKEN" \
  --header 'Accept: application/json' \
  --data-urlencode 'limit=5' \
  --data-urlencode 'offset=0' \
  --data-urlencode 'sort=+id'

The v2 response contains contacts, pagination, and sort. Use Pagination and sorting to traverse the selection; five returned contacts do not mean the directory contains only five.

For a focused search, save this as contact-search.json. Replace the illustrative tag name with one used in your account:

{
  "query": {
    "contact_type": { "$eq": "person" },
    "tag.name": { "$any": ["Product launch"] }
  },
  "sort": "+id",
  "limit": 5,
  "offset": 0
}
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/contacts/search' \
  --header "Authorization: Bearer $PREZLY_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data-binary @contact-search.json

Search is a read despite using POST. Contact filters have their own field/operator combinations; use Search Contacts, rather than assuming a story filter works for contacts too.

Choose a returned ID and replace YOUR_CONTACT_ID:

curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/contacts/YOUR_CONTACT_ID' \
  --header "Authorization: Bearer $PREZLY_API_TOKEN" \
  --header 'Accept: application/json'

The response contains contact. Inspect contact_type, names, emails, primary_email, and tags before using the record. tags contains names; tag_entities in the current response contains the corresponding tag references. Audience rules that expect tag IDs need those numeric IDs, not the names.

List Contacts → · Get Contact →

Create a person or organisation

Create only after checking whether your integration already has a mapped record. Save this illustrative person as new-contact.json, replacing the identity and address with the intended data:

{
  "contact_type": "person",
  "first_name": "Alex",
  "last_name": "Rivera",
  "emails": ["alex@example.test"],
  "tags": ["Product launch"]
}
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/contacts' \
  --header "Authorization: Bearer $PREZLY_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data-binary @new-contact.json

The v2 implementation returns 201 Created with contact; save contact.id before continuing.

For an organisation, use contact_type: organisation and company_name, rather than person-only fields such as first_name or function_name. A person needs identifying information; an otherwise empty record is rejected. An organisation needs its company name.

Tag names and a person's organisation names can resolve existing records or create missing ones. Review those values before importing: spelling variations can create unwanted tags or organisations. This workflow creates individual contacts; it does not invoke the separate bulk-import system.

Create Contact →

Update only the fields you intend to change

Read the record immediately before changing it. This example changes a person's job title and preserves omitted fields:

curl --fail-with-body --silent --show-error --request PATCH 'https://api.prezly.com/v2/contacts/YOUR_CONTACT_ID' \
  --header "Authorization: Bearer $PREZLY_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '{"function_name":"Science editor"}'

The response contains contact. A PATCH is partial at the field level, but supplied collections such as emails, tags, languages, or organisations replace that collection. Supplying one new email address is not an append; read, reconcile, and send the complete intended list. An empty list deliberately clears it. Do not write every response field back as a request, or send contact_type to change a record's kind.

Use the Update Contact request fields for the existing contact type. A fresh read is useful but is not an atomic version check; coordinate writers to avoid overwriting another editor's collection changes.

For an avatar, avatar_image takes a JSON-encoded image string, or null to clear it. The response returns a structured image object, so do not copy that object directly into a write request. See Images and files for image metadata. social_accounts uses the supported network names in the request schema, including Bluesky, Threads, and TikTok.

Update Contact →

Keep contact changes separate from outreach

Changes to names and email addresses can update recipients in draft campaigns asynchronously. Recheck the actual campaign audience before sending; a previously inspected draft is not frozen when a contact is edited.

Creating, tagging, or editing a contact does not establish subscription consent. Use Subscriptions and preferences for explicit preference changes. Removing a recipient from one campaign is also different from unsubscribing an address or deleting the CRM record. Do not recreate an unsubscribed contact to work around a delivery restriction.

Delete Contact is a separate action on a selected record. Do not use deletion as the way to remove someone from one campaign. Review related records and keep your source-system mapping consistent if you deliberately delete a contact.

If Create times out, reconcile the mapping and search before trying again; otherwise you can create duplicate records. For validation/permission failures, inspect Handling errors. Continue with Campaign audiences or Individual pitches.

On this page