# Contact properties

> Store extra data on contacts with default and custom properties, then use them to personalize campaigns.

Contact properties store additional information about your contacts that you can then use to personalize your [campaigns](https://www.mailblastr.com/docs/campaigns/managing). Alongside a set of default properties, you can define your own **custom properties**.

## Default properties

Every contact already carries these built-in properties:

- `first_name` — the contact’s first name.
- `last_name` — the contact’s last name.
- `email` — the contact’s email address.
- `unsubscribed` — whether the contact has unsubscribed from all campaigns.

## Custom properties

Create additional custom properties to store whatever you need — a company name, a plan tier, a signup source. Each property has a key, a value, and an optional fallback value.

**Property fields**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | Yes | The property name. Alphanumeric and underscores only, max 50 characters. Case-sensitive. |
| `type` | string | Yes | Either `string` or `number`. |
| `fallback_value` | string | number | No | Used for contacts that have no value set for this property. Must match `type`. |

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.contactProperties.create({
  "key": "company_name",
  "type": "string",
  "fallback_value": "Acme Corp"
});
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

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

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

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

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

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

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("POST", "https://api.mailblastr.com/contact-properties", strings.NewReader(`{
  "key": "company_name",
  "type": "string",
  "fallback_value": "Acme Corp"
}`))
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    req.Header.Set("Content-Type", "application/json")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .post("https://api.mailblastr.com/contact-properties")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .header("Content-Type", "application/json")
        .body(r#"{
  "key": "company_name",
  "type": "string",
  "fallback_value": "Acme Corp"
}"#)
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/contact-properties"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "key": "company_name",
  "type": "string",
  "fallback_value": "Acme Corp"
}
"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.mailblastr.com/contact-properties");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
request.Content = new StringContent(@"{
  ""key"": ""company_name"",
  ""type"": ""string"",
  ""fallback_value"": ""Acme Corp""
}", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/contact-properties' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "key": "company_name",
  "type": "string",
  "fallback_value": "Acme Corp"
}'
```

**CLI**

```bash
mailblastr contact-properties create \
  --key 'company_name' \
  --type 'string' \
  --fallback-value 'Acme Corp'
```

## Setting a value on a contact

A property’s fallback value is used for any contact that has no explicit value. To set a per-contact value, pass a `properties` object when you [create a contact](https://www.mailblastr.com/docs/api/contacts-create) or [update one](https://www.mailblastr.com/docs/api/contacts-update). You can update a contact by `id` or by `email`.

**cURL**

```bash
# Set a property while creating a contact
curl -X POST 'https://api.mailblastr.com/contacts' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "steve@example.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": false,
    "properties": { "company_name": "Acme Corp" }
  }'

# Or update an existing contact by email
curl -X PATCH 'https://api.mailblastr.com/contacts/steve@example.com' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "properties": { "company_name": "Acme Corp" } }'
```

**Node.js**

```js
// Set a property while creating a contact
await fetch('https://api.mailblastr.com/contacts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mb_xxxxxxxxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'steve@example.com',
    first_name: 'Steve',
    last_name: 'Wozniak',
    unsubscribed: false,
    properties: { company_name: 'Acme Corp' },
  }),
});

// Or update an existing contact by email
await fetch('https://api.mailblastr.com/contacts/steve@example.com', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Bearer mb_xxxxxxxxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ properties: { company_name: 'Acme Corp' } }),
});
```

**Python**

```python
import requests

# Set a property while creating a contact
requests.post(
    "https://api.mailblastr.com/contacts",
    headers={"Authorization": "Bearer mb_xxxxxxxxx"},
    json={
        "email": "steve@example.com",
        "first_name": "Steve",
        "last_name": "Wozniak",
        "unsubscribed": False,
        "properties": {"company_name": "Acme Corp"},
    },
)

# Or update an existing contact by email
requests.patch(
    "https://api.mailblastr.com/contacts/steve@example.com",
    headers={"Authorization": "Bearer mb_xxxxxxxxx"},
    json={"properties": {"company_name": "Acme Corp"}},
)
```

## Validation rules

A property is only applied to a contact if the property **key already exists** and the supplied value matches the property’s declared **type**. Otherwise the value is not set and the call fails with an error.

- **Unknown key** — if the property key does not exist, it is not added and the request fails.
- **Wrong type** — if the value’s type does not match the property’s `type`, it is not added and the request fails.
- **Case-sensitive keys** — `company_name`, `CompanyName`, and `company_Name` are three different keys. Match the key exactly.

> **Note:** List every property you have defined with [GET /contact-properties](https://www.mailblastr.com/docs/audiences/properties) to confirm the exact keys and types before setting values.

## Using properties in campaigns

Reference any property — default or custom — in your campaign HTML and text content to personalize each recipient’s message. Properties are resolved per-contact when the campaign is sent, using each contact’s value or the property’s fallback. You can also set this up when you [create a campaign](https://www.mailblastr.com/docs/api/campaigns-create) via the API.
