---
title: "New Contacts Experience"
slug: new-contacts-experience
description: "Store custom properties on your contacts, track their activity, and segment them as you need."
created_at: "2025-11-05"
updated_at: "2025-11-05"
image: "https://cdn.resend.com/posts/new-contacts-experience-cover-for-blog.jpg"
humans: ["alexandre-cisneiros", "cassio-zen", "danilo-woznica", "vitor-capretz", "zeh-fernandes"]
featured: true
category: "product"
---

Today, we're excited to announce some new features for [Contacts](https://resend.com/docs/dashboard/audiences/contacts). These improvements will supercharge your ability to personalize and segment your Contacts on Resend.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience.mp4"
  poster="https://cdn.resend.com/posts/new-contacts-experience-poster.jpg"
  controls
  className="extraWidth"
/>

## Custom Contact Properties

In addition to the standard fields you can already set on a Contact, such as `FIRST_NAME` and `LAST_NAME`, you can now store custom properties on your Contacts.

These properties can be used to personalize your Broadcasts across all Segments.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience-1.mp4"
  controlsList="nodownload"
  playsInline
  autoPlay
  loop
  muted
  className="extraWidth aspect-video"
/>

Properties can have a fallback value, which will be used when a Contact doesn't yet have an explicit value for the property.

You can create Contact properties [via the API or SDKs](/docs/api-reference/contact-properties/create-contact-property).

<CodeTabs codeHeight={210}>

```nodejs
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.create({
    key: 'company_name',
    type: 'string',
    fallbackValue: 'Acme Corp',
  });
  ```

  ```php
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->create([
    'key' => 'company_name',
    'type' => 'string',
    'fallback_value' => 'Acme Corp',
  ]);
  ```

  ```python
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "key": "company_name",
      "type": "string",
      "fallback_value": "Acme Corp",
  }

  contact_property = resend.ContactProperties.create(params)
  ```

  ```ruby
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  property = Resend::ContactProperties.create({
    key: "company_name",
    type: "string",
    fallback_value: "Acme Corp"
  })
  ```

  ```go
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	apiKey := "re_xxxxxxxxx"

  	client := resend.NewClient(apiKey)

  	params := &resend.CreateContactPropertyRequest{
  		Key:           "company_name",
  		Type:          "string",
  		FallbackValue: "Acme Corp",
  	}

  	property, err := client.ContactProperties.CreateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust
  use resend_rs::{
    types::{CreateContactPropertyOptions, PropertyType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact_property = CreateContactPropertyOptions::new("company_name", PropertyType::String)
      .with_fallback("Acme Corp");

    let _contact_property = resend.contacts.create_property(contact_property).await?;

    Ok(())
  }
  ```

  ```java
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      CreateContactPropertyOptions options = CreateContactPropertyOptions.builder()
        .key("company_name")
        .type("string")
        .fallbackValue("Acme Corp")
        .build();

      resend.contactProperties().create(options);
    }
  }
  ```

  ```dotnet
  // C# SDK is not available yet
  ```

  ```curl
  curl -X POST 'https://api.resend.com/contact-properties' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "key": "company_name",
    "type": "string",
    "fallback_value": "Acme Corp"
  }'
  ```
</CodeTabs>

## Assign Custom Values to Contacts

Once you've created a property, you can assign values for it to any Contact.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience-5.mp4"
  controls
  controlsList="nodownload"
  playsInline
  autoPlay
  loop
  muted
  className="extraWidth aspect-video"
/>

Of course, you can also assign values to Contact properties [using the API or SDKs](/docs/api-reference/contacts/create-contact).

## Use Contact Properties in Broadcasts

Properties can then be used to personalize your broadcasts. If you do not provide a Contact property value, the fallback value will be used.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience-2.mp4"
  controlsList="nodownload"
  playsInline
  autoPlay
  loop
  muted
  className="extraWidth aspect-video"
/>

Properties can also be used in [Broadcasts sent using the API](/docs/api-reference/broadcasts/create-broadcast).

## Contact Activity History

We've introduced a new activity history view for Contacts to give you a comprehensive timeline of all events related to a Contact, including when it was created, unsubscribed or received an email.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience-3.mp4"
  controlsList="nodownload"
  playsInline
  autoPlay
  loop
  muted
  className="extraWidth aspect-video"
/>

## Segmenting Contacts

Previously, each Contact you created could only be part of a single Audience. This means if you wanted to segment a Contact into multiple Audiences, you had to create a new Contact with the same email address each time.

Now, we're making it more flexible. A Contact can now be a part of zero, one, or multiple Audiences as needed. A Contact that is in more than one Audience now counts as a single Contact in your quota.

And to make this distinction clearer, we've renamed Audiences to Segments.

<video
  src="https://cdn.resend.com/posts/new-contacts-experience-4.mp4"
  controlsList="nodownload"
  playsInline
  autoPlay
  loop
  muted
  className="extraWidth aspect-video"
/>

Now that Contacts don't belong to a single Segment, you can reference them directly in your API calls. We have a new `/contacts` endpoint that allows you to see and manage your contacts, and our SDKs have been updated to not require the `audience_id` parameter for these requests.

<CodeTabs codeHeight={210}>
```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.contacts.list();
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->contacts->list();
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

resend.Contacts.list()
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

Resend::Contacts.list()
```

```go
import "github.com/resend/resend-go/v3"

client := resend.NewClient("re_xxxxxxxxx")

contacts, err := client.Contacts.List()
```

```rust
use resend_rs::{Resend, Result, list_opts::ListOptions};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let _contacts = resend
    .contacts
    .list(
        ListOptions::default(),
    )
    .await?;

  Ok(())
}
```

```java
import com.resend.*;

public class Main {
    public static void main(String[] args) {
        Resend resend = new Resend("re_xxxxxxxxx");

        ListContactsResponseSuccess data = resend.contacts().list();
    }
}
```

```dotnet
using Resend;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

var resp = await resend.ContactListAsync();
Console.WriteLine( "Nr Contacts={0}", resp.Content.Count );
```

```curl
curl -X GET 'https://api.resend.com/contacts' \
     -H 'Authorization: Bearer re_xxxxxxxxx'
```

</CodeTabs>

## Global Contact Model

Starting today, Contacts are now global entities, identified by their email address.

How does this help you?

- You get a more accurate view of your interaction with each Contact
- You can personalize your broadcasts to each Contact
- You can segment your Contacts as you need
- You can assign a Contact to zero, one, or multiple Audiences
- We count your Contacts once, even if they are in multiple Audiences

## Conclusion

We can't wait to see how you use these new features to send more personalized emails to your contacts. We have more updates planned for Contacts, so stay tuned!

For more information on how to use Contacts, including a [migration guide](/docs/dashboard/segments/migrating-from-audiences-to-segments) for those who are already using Audiences for segmentation, check out the [new Contacts documentation](/docs/dashboard/audiences/introduction).