Skip to main content

Manage Custom Fields

View and update the contact structure that determines which fields are available on your contacts.

Goal

By the end of this guide you will be able to retrieve your contact structure with its fields and tags, and update it to add or modify custom fields.

Prerequisites

  • An API key with contacts:write scope (for updating the structure) or contacts:read scope (for read-only access)
  • Your API base URL (found on the Settings > API Keys page)

Background

A contact structure defines the schema for your contacts. It includes:
  • A key name and key type — the primary identifier for contacts (typically “Email” of type “email”)
  • Fields — custom fields like First Name, Last Name, Company, Phone, etc.
  • Tags — label definitions that can be assigned to contacts
Every contact belongs to exactly one contact structure. Your account has a default contact structure that was created when the account was set up. Note: Creating new contact structures via API key is not supported. Use the Benchmark Email web application to create additional structures if needed. API keys can read and update existing structures.

Steps

1. List all contact structures

Retrieve all contact structures in your account.
curl https://api-us-west-2-c1.benchmarkemail.com/api/contact-structure \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
Response (200 OK):
[
  {
    "_id": "64a1b2c3d4e5f6a7b8c9d0e1",
    "label": "Default Contacts",
    "keyName": "Email",
    "keyType": "email",
    "fields": [
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d100",
        "label": "First Name",
        "dataType": "text",
        "required": false,
        "predefinedField": "firstName"
      },
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d101",
        "label": "Last Name",
        "dataType": "text",
        "required": false,
        "predefinedField": "lastName"
      },
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d102",
        "label": "Company",
        "dataType": "text",
        "required": false
      }
    ],
    "tags": [
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d300",
        "label": "VIP"
      },
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d301",
        "label": "Prospect"
      }
    ]
  }
]
Key takeaway: The _id values of the fields array are what you use when creating or updating contacts and when searching by custom field values.

2. Get a specific contact structure

Retrieve a single contact structure by its ID.
curl https://api-us-west-2-c1.benchmarkemail.com/api/contact-structure/64a1b2c3d4e5f6a7b8c9d0e1 \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
Response (200 OK):
{
  "_id": "64a1b2c3d4e5f6a7b8c9d0e1",
  "label": "Default Contacts",
  "keyName": "Email",
  "keyType": "email",
  "fields": [
    {
      "_id": "64a1b2c3d4e5f6a7b8c9d100",
      "label": "First Name",
      "dataType": "text",
      "required": false,
      "predefinedField": "firstName"
    },
    {
      "_id": "64a1b2c3d4e5f6a7b8c9d101",
      "label": "Last Name",
      "dataType": "text",
      "required": false,
      "predefinedField": "lastName"
    },
    {
      "_id": "64a1b2c3d4e5f6a7b8c9d102",
      "label": "Company",
      "dataType": "text",
      "required": false
    }
  ],
  "tags": [
    { "_id": "64a1b2c3d4e5f6a7b8c9d300", "label": "VIP" },
    { "_id": "64a1b2c3d4e5f6a7b8c9d301", "label": "Prospect" }
  ],
  "__v": 3
}

3. Update a contact structure

Use PUT to update a contact structure. This replaces the full structure, so include all existing fields plus any changes. Include the current __v value for optimistic concurrency control. Adding a new “Loyalty Tier” field to an existing structure:
curl -X PUT https://api-us-west-2-c1.benchmarkemail.com/api/contact-structure/64a1b2c3d4e5f6a7b8c9d0e1 \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Default Contacts",
    "keyName": "Email",
    "fields": [
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d100",
        "label": "First Name",
        "dataType": "text",
        "required": false,
        "predefinedField": "firstName"
      },
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d101",
        "label": "Last Name",
        "dataType": "text",
        "required": false,
        "predefinedField": "lastName"
      },
      {
        "_id": "64a1b2c3d4e5f6a7b8c9d102",
        "label": "Company",
        "dataType": "text",
        "required": false
      },
      {
        "label": "Loyalty Tier",
        "dataType": "text",
        "required": false
      }
    ],
    "tags": [
      { "_id": "64a1b2c3d4e5f6a7b8c9d300", "label": "VIP" },
      { "_id": "64a1b2c3d4e5f6a7b8c9d301", "label": "Prospect" }
    ],
    "__v": 3
  }'
Response (200 OK):
{
  "_id": "64a1b2c3d4e5f6a7b8c9d0e1",
  "label": "Default Contacts",
  "keyName": "Email",
  "keyType": "email",
  "fields": [
    { "_id": "64a1b2c3d4e5f6a7b8c9d100", "label": "First Name", "dataType": "text", "required": false, "predefinedField": "firstName" },
    { "_id": "64a1b2c3d4e5f6a7b8c9d101", "label": "Last Name", "dataType": "text", "required": false, "predefinedField": "lastName" },
    { "_id": "64a1b2c3d4e5f6a7b8c9d102", "label": "Company", "dataType": "text", "required": false },
    { "_id": "64a1b2c3d4e5f6a7b8c9d103", "label": "Loyalty Tier", "dataType": "text", "required": false }
  ],
  "tags": [
    { "_id": "64a1b2c3d4e5f6a7b8c9d300", "label": "VIP" },
    { "_id": "64a1b2c3d4e5f6a7b8c9d301", "label": "Prospect" }
  ],
  "__v": 4
}
Supported field data types:
  • text — free-text string
  • number — numeric value
  • date — date value
  • boolean — true/false
  • recurrent_date — recurring date (month/day)
Predefined fields: Use predefinedField to map standard fields like firstName, lastName. These enable features like merge tags in email campaigns. Important notes:
  • PUT is a full replacement. Include all existing fields you want to keep, or they will be removed.
  • When adding a new field, omit _id — the server generates it.
  • When keeping existing fields, include their _id to preserve them.
  • Include the current __v value for optimistic concurrency control.
  • Removing a field that is referenced by a published signup form will return a 400 error with details about which forms are affected.

Common Errors

StatusErrorCauseFix
401UnauthorizedErrorInvalid or inactive API keyVerify your key in Settings > API Keys
403ForbiddenErrorKey lacks contacts:write scopeUpdate operations require contacts:write
403ForbiddenErrorAttempted to create a new contact structure via API keyCreating contact structures is not available via API key. Use the web application
400ValidationErrorMissing required properties (label, keyName), or invalid field dataTypeCheck request body against the schema requirements
400ContactFieldInUseErrorTried to remove a field used by a signup formUpdate or unpublish the affected form first. The error response includes debug.affectedForms with form IDs and names
404RecordNotFoundContact structure ID does not existVerify the structure ID
429TooManyRequestsErrorRate limit exceededWait for the Retry-After period. See Rate Limits

Next Steps